Mar 26, 2026·6 min read·29 visits
Vikunja < 2.2.1 contains an SSRF flaw in its migration module due to unvalidated third-party URLs. Authenticated attackers can exploit this to read internal network data, such as cloud metadata services. The issue is resolved in version 2.2.2 via a centralized SSRF-safe HTTP client.
A Server-Side Request Forgery (SSRF) vulnerability in Vikunja versions prior to 2.2.1 allows authenticated users to exfiltrate internal network resources during task migration operations.
Vikunja is an open-source task management platform that includes features for migrating data from external services. The migration modules interface with third-party APIs to retrieve tasks, metadata, and file attachments. This functionality exposes a Server-Side Request Forgery (SSRF) attack surface if the URLs provided by the external API are not strictly validated.
The vulnerability, tracked as CVE-2026-33675, exists in the migration helper functions responsible for fetching remote file attachments. Versions of Vikunja prior to 2.2.1 fail to restrict the destination IP addresses during these fetch operations. An attacker with privileges to initiate a migration can exploit this flaw to coerce the Vikunja server into making arbitrary HTTP requests.
Successful exploitation results in the exfiltration of internal network data. The server processes the internal response and stores it as a task attachment, which the attacker can subsequently download. This allows an authenticated user to bypass external firewalls and access internal services, including cloud provider metadata endpoints.
The vulnerability stems from the implementation of the DownloadFile and DownloadFileWithHeaders functions located in pkg/modules/migration/helpers.go. These functions are tasked with retrieving remote assets specified by the third-party service during a data migration. The code utilizes the standard Go http.Client{} struct without any custom dialer or transport configuration.
The standard http.Client{} natively follows HTTP redirects and resolves domain names to IP addresses without restrictions. When a third-party API returns a URL, the application passes this URL directly to the http.Client.Do() method. The application performs no pre-flight checks on the hostname or the resolved IP address to verify if the destination is a public, routable endpoint.
Because the application implicitly trusts the URLs provided by the external service, it acts as a confused deputy. If the external service returns a URL pointing to a private IPv4 address (RFC 1918) or a non-routable metadata IP, the standard HTTP client initiates the connection. The response body is then read into a buffer and processed as a legitimate file attachment.
Prior to the patch, the DownloadFileWithHeaders function initialized a default HTTP client for every file download. The code lacked any mechanisms to intercept the connection process or validate the target destination. The vulnerability was explicitly ignored by a security linter comment, incorrectly assuming that URLs from a migration provider API were inherently safe.
func DownloadFileWithHeaders(url string, headers http.Header) (buf *bytes.Buffer, err error) {
// Request setup omitted
hc := http.Client{}
resp, err := hc.Do(req) // #nosec G704 -- URL is from migration provider API
// Response processing omitted
}The remediation introduced in commit 93297742236e3d33af72c993e5da960db01d259e replaces the default client with a specialized SSRF-safe alternative. The utils.NewSSRFSafeHTTPClient() function returns a client configured with a custom DialContext. This dialer hooks into the connection phase, resolving the hostname and verifying that the resulting IP address is not within restricted or private ranges.
func DownloadFileWithHeaders(url string, headers http.Header) (buf *bytes.Buffer, err error) {
// Request setup omitted
hc := utils.NewSSRFSafeHTTPClient()
resp, err := hc.Do(req)
// Response processing omitted
}Exploitation requires the attacker to possess a user account on the target Vikunja instance with permissions to initiate task migrations. The attacker must also control an account on a supported third-party migration provider, such as Todoist or Trello. The initial step involves creating a crafted task within the third-party platform.
The attacker configures the file attachment URL of the crafted task to point to an internal resource. A common target in cloud environments is the metadata service at http://169.254.169.254/latest/meta-data/. Once the malicious payload is staged on the external provider, the attacker instructs the Vikunja application to begin the migration process.
The Vikunja server parses the task data from the external provider and invokes the vulnerable download function on the attacker-supplied URL. The server issues an HTTP GET request to the internal IP address, receives the sensitive data, and saves it as an attachment to the newly migrated task. The attacker completes the exfiltration by downloading the attachment from the Vikunja user interface.
The vulnerability allows an authenticated attacker to read data from services located within the same network as the Vikunja application server. This compromises the confidentiality of internal resources that are intentionally isolated from the public internet. The CVSS v3.1 base score of 6.4 reflects the medium severity, driven by the requirement for authentication and the changed scope of the attack.
In cloud deployments, the impact is elevated if the server can reach instance metadata endpoints. An attacker can retrieve temporary IAM credentials, user data scripts, and configuration variables. Access to these credentials facilitates lateral movement and privilege escalation within the broader cloud environment.
For on-premises deployments, the attacker can target internal administrative interfaces, unauthenticated databases, or unpatched internal microservices. While the vulnerability does not directly grant arbitrary code execution on the Vikunja server, the exposure of internal infrastructure presents a significant risk to the organization.
The primary remediation strategy is to upgrade the Vikunja application to version 2.2.2 or later. While version 2.2.1 addressed the specific vulnerable functions in the migration module, version 2.2.2 implements a centralized SSRF protection mechanism. This comprehensive fix applies the SSRF-safe HTTP client to all outgoing requests, including webhooks and avatar fetches.
Administrators must review the application configuration after upgrading to ensure the protections are active. The 2.2.2 release introduces an outgoingrequests configuration block in config.yml. The OutgoingRequestsAllowNonRoutableIPs setting must remain configured to false in production environments.
Organizations should implement network segmentation as a defense-in-depth measure. The Vikunja application server should reside in an isolated network segment with strict egress firewall rules. Blocking access to the 169.254.169.254 IP address at the host firewall level prevents SSRF vulnerabilities from exposing cloud metadata.
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 v3.1 | 6.4 (Medium) |
| EPSS Score | 0.00034 (0.03%) |
| Impact | Information Disclosure, Internal Reconnaissance |
| Exploit Status | No known public exploits (None) |
| Authentication | Required (Low Privileges) |
The web application receives a URL or similar request from an upstream component and retrieves the contents of this URL, but it does not sufficiently ensure that the request is being sent to the expected destination.
Home Assistant Core prior to version 2026.2.3 is vulnerable to Server-Side Request Forgery (SSRF) via the IPP integration's auto-discovery mechanism. Unauthenticated mDNS advertisements can trigger HTTP requests that follow malicious redirects to loopback interfaces.
CVE-2026-91130 is a critical DOM-based Cross-Site Scripting (XSS) vulnerability in the Home Assistant open-source home automation platform. Prior to version 2026.7.0, the Statistics Graph card rendered series tooltips using raw HTML string interpolation without escaping user-controlled entity friendly names. By abusing this vulnerability, an authenticated user with low-privilege access can inject arbitrary HTML and JavaScript into entity name fields, which executes in the context of an administrative user's browser session upon hovering over a data point on an affected chart.
A high-severity denial of service vulnerability exists in the emiago/sipgo Go library when parsing stream-based SIP messages. The stream parser fails to validate declared Content-Length header sizes before initiating memory allocations, allowing remote, unauthenticated attackers to trigger process memory exhaustion and application crashes.
CVE-2026-58270 identifies a Regular Expression Denial of Service (ReDoS) vulnerability in Sync-in Server prior to version 2.4.0. An authenticated attacker can supply a complex regular expression in the pathFilters parameter of the sync diff endpoint. When evaluated, this causes catastrophic backtracking, blocking the single-threaded Node.js event loop and rendering the entire server unresponsive.
CVE-2026-56681 is a high-severity authentication bypass vulnerability in 9Router, an AI router and token-saving proxy. The vulnerability arises from an improper trust boundary where the application relies on the client-controlled HTTP header X-9r-Real-Ip to determine whether an incoming request originates from a local (loopback) environment. In deployments where requests can reach the Next.js backend directly—bypassing the sanitizing custom-server.js wrapper—a remote, unauthenticated attacker can spoof their origin by supplying an X-9r-Real-Ip: 127.0.0.1 header.
A rate limiting bypass vulnerability in 9Router versions before 0.5.6 allows unauthenticated remote attackers to circumvent the login progressive lockout mechanism. By manipulating the client-supplied X-9r-Real-Ip HTTP header, an attacker can rotate the tracking IP address, enabling unthrottled brute-force password guessing against the administrative interface.