Mar 26, 2026·7 min read·2 visits
Vikunja < 2.2.1 is vulnerable to SSRF via the OIDC picture claim. The application fails to validate the target IP when downloading user avatars, allowing authenticated attackers to scan internal networks or access cloud metadata services.
Vikunja versions prior to 2.2.1 contain a Server-Side Request Forgery (SSRF) vulnerability in the OpenID Connect (OIDC) authentication module. The application fails to validate destination IP addresses when fetching user avatars from OIDC provider claims, allowing attackers to target internal network services.
Vikunja, a self-hosted task management platform, contains a Server-Side Request Forgery (SSRF) vulnerability in its OpenID Connect (OIDC) authentication module. The flaw resides in the avatar downloading component, specifically within pkg/utils/avatar.go. Versions prior to 2.2.1 are affected by this issue.
The vulnerability triggers when a user authenticates via a third-party OIDC provider. During the authentication flow, Vikunja processes the picture claim provided by the OIDC identity provider. The server attempts to fetch the image file from the specified URL to store as the user's local avatar.
The implementation fails to validate the destination IP address or restrict the network ranges targeted by the outbound HTTP request. An attacker with the ability to modify their OIDC profile can supply arbitrary URLs, including those pointing to internal network resources. This behavior constitutes a classic SSRF (CWE-918) condition.
The severity is rated Medium (CVSS 6.4) due to the requirement for authentication and the limited scope of direct data exfiltration. The vulnerability primarily facilitates internal network reconnaissance and potential interaction with unauthenticated internal services.
The root cause of CVE-2026-33679 is the instantiation and use of a default Go http.Client{} for processing external, user-influenced URLs. The DownloadImage function in pkg/utils/avatar.go receives the target URL directly from the OIDC picture claim. The application implicitly trusts the OIDC provider's data without independent sanitization.
The default Go HTTP client does not restrict the destination of its requests. It willingly resolves local hostnames, processes RFC 1918 private IP addresses, and routes traffic to loopback interfaces. The implementation lacks a custom Transport or DialContext designed to enforce network boundary policies.
The developer explicitly bypassed internal security scanning by adding a #nosec G704 annotation to the HTTP request call. The comment associated with this suppression indicates an assumption that URLs originating from an OIDC provider are inherently safe. This assumption proves false when attackers control their identity provider or use flexible providers that allow custom profile data.
The vulnerability bypasses existing SSRF protections within the Vikunja codebase. The application implements safe HTTP clients for its webhook processing features, but these controls were not universally applied. This discrepancy highlights a failure in standardized security control deployment across different feature modules.
An examination of pkg/utils/avatar.go in the vulnerable version reveals the direct usage of the insecure HTTP client. The DownloadImage function constructs an HTTP request and executes it immediately. The code directly passes the unvalidated URL string to the client.
func DownloadImage(url string) ([]byte, error) {
// Request initialization omitted
// #nosec G704 -- URL comes from OIDC provider picture claim
resp, err := (&http.Client{}).Do(req)
if err != nil {
return nil, fmt.Errorf("failed to download image: %w", err)
}
// Response processing omitted
}The presence of the #nosec directive confirms the developer recognized the theoretical risk but dismissed it based on the data source. The default client executes the request without checking the resolved IP address against an allowlist or denylist.
The patch introduced in commit 363aa6642352b08fc8bc6aaff2f3a550393af1cf addresses this flaw by replacing the default client. The developers substituted (&http.Client{}) with a custom NewSSRFSafeHTTPClient() function.
--- a/pkg/utils/avatar.go
+++ b/pkg/utils/avatar.go
@@ -101,7 +101,7 @@ func DownloadImage(url string) ([]byte, error) {
return nil, fmt.Errorf("failed to create HTTP request: %w", err)
}
- resp, err := (&http.Client{}).Do(req) // #nosec G704 -- URL comes from OIDC provider picture claim
+ resp, err := NewSSRFSafeHTTPClient().Do(req)
if err != nil {
return nil, fmt.Errorf("failed to download image: %w", err)
}The NewSSRFSafeHTTPClient() implementation enforces network routing restrictions. It typically utilizes a custom dialer that resolves the hostname and validates the resulting IP address before initiating the TCP connection, thereby mitigating Time-of-Check Time-of-Use (TOCTOU) attacks like DNS rebinding.
Exploiting CVE-2026-33679 requires the attacker to authenticate to the target Vikunja instance using OpenID Connect. The attacker must possess an account on an OIDC provider trusted by the Vikunja server, or the server must permit arbitrary OIDC registrations. The attacker configures their OIDC profile to include a malicious URL in the picture claim.
The payload URL targets internal infrastructure inaccessible from the public internet. Common targets include cloud provider metadata services (e.g., http://169.254.169.254/latest/meta-data/ on AWS), local administrative interfaces running on 127.0.0.1, or internal corporate network segments. The attacker then initiates the OIDC login flow on the Vikunja instance.
Upon successful authentication, Vikunja retrieves the user profile and triggers the DownloadImage routine. The server initiates an HTTP GET request to the attacker-specified destination. The application expects the response to be a valid image file and attempts to process it as such.
Attackers infer the state of internal services through side channels. While direct exfiltration of the HTTP response body is limited because the application expects image formatting, attackers can measure response timing to perform internal port scanning. They can also analyze application error messages to differentiate between connection timeouts, connection refusals, and successful HTTP responses from non-image endpoints.
The primary impact of this SSRF vulnerability is unauthorized network access from the perspective of the Vikunja application server. The attacker leverages the server as a proxy to interact with systems residing within the same network security boundary. This breaks network segmentation and exposes internally routed services.
The CVSS v3.1 base score of 6.4 reflects the medium severity of the flaw. The Scope: Changed (S:C) metric indicates that the vulnerability impacts resources beyond the vulnerable application itself. The Confidentiality: Low (C:L) metric accounts for the limited ability to read internal data, constrained by the application's attempt to parse the response as an image.
Cloud environments face the highest risk from this vulnerability. An attacker targeting a Vikunja instance hosted on AWS, GCP, or Azure can query the instance metadata service. Depending on the metadata service version and configuration, the attacker may retrieve sensitive information, including temporary IAM credentials or deployment scripts.
The vulnerability does not directly permit Remote Code Execution (RCE) or arbitrary file read on the Vikunja server. However, it can be chained with vulnerabilities in other internal services. If an internal unauthenticated REST API is accessible via GET requests, the attacker can use the Vikunja server to trigger state-changing operations on that API.
The official remediation for CVE-2026-33679 is to upgrade Vikunja to version 2.2.1 or later. The release of version 2.2.1 incorporates the commit 363aa6642352b08fc8bc6aaff2f3a550393af1cf, which securely implements the HTTP client used for avatar downloads. Administrators should verify their deployments are running the patched version.
System administrators can implement network-level mitigations if immediate patching is not feasible. Egress filtering rules on the firewall or host-level packet filter (e.g., iptables, nftables) can restrict the Vikunja server from initiating connections to RFC 1918 space or cloud metadata IP addresses. The server should only be permitted to contact required external services and trusted OIDC providers.
Cloud administrators should enforce IMDSv2 (Instance Metadata Service Version 2) on AWS environments. IMDSv2 requires a specific HTTP header (X-aws-ec2-metadata-token) to retrieve metadata, which mitigates simple GET-based SSRF vulnerabilities like this one. Similar protections exist for other major cloud providers and should be enabled.
Security teams should review application logs for anomalous outbound connections originating from the Vikunja process. High volumes of connections to internal IP addresses or repeated authentication attempts associated with unusual OIDC provider URLs indicate potential exploitation attempts.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:N/A:L| Product | Affected Versions | Fixed Version |
|---|---|---|
Vikunja go-vikunja | < 2.2.1 | 2.2.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-918 |
| Attack Vector | Network |
| CVSS Score | 6.4 |
| EPSS Score | 0.00034 |
| Impact | Internal Network Scanning / Metadata Access |
| Exploit Status | Unexploited in the wild |
| KEV Status | Not Listed |
Server-Side Request Forgery (SSRF)