VYPR
Moderate severityNVD Advisory· Published Mar 24, 2026· Updated Mar 24, 2026

Vikunja has SSRF via Todoist/Trello Migration File Attachment URLs that Allows Reading Internal Network Resources

CVE-2026-33675

Description

Vikunja is an open-source self-hosted task management platform. Prior to version 2.2.1, the migration helper functions DownloadFile and DownloadFileWithHeaders in pkg/modules/migration/helpers.go make arbitrary HTTP GET requests without any SSRF protection. When a user triggers a Todoist or Trello migration, file attachment URLs from the third-party API response are passed directly to these functions, allowing an attacker to force the Vikunja server to fetch internal network resources and return the response as a downloadable task attachment. Version 2.2.1 patches the issue.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Vikunja before 2.2.1 has an SSRF vulnerability in migration helper functions that allows an attacker to force the server to fetch internal network resources.

Vulnerability

CVE-2026-33675 is a server-side request forgery (SSRF) vulnerability in Vikunja, an open-source self-hosted task management platform. The flaw resides in the migration helper functions DownloadFile and DownloadFileWithHeaders in pkg/modules/migration/helpers.go. These functions make arbitrary HTTP GET requests without any SSRF protection, such as URL validation, private IP blocklists, redirect restrictions, or response size limits [1][2].

Exploitation

When a user triggers a Todoist or Trello migration, file attachment URLs from the third-party API response of the third-party API are passed directly to these vulnerable functions. An attacker can craft a malicious Todoist or Trello project containing attachment URLs that point to internal network resources (e.g., http://169.254.169.254/). When the migration is initiated, the Vikunja server fetches those URLs and returns the response as a downloadable task attachment, effectively allowing the attacker to read internal resources [2].

Impact

An attacker with the ability to trigger a migration (or trick a user into doing so) can force the Vikunja server to make HTTP requests to internal services, potentially accessing sensitive data such as cloud metadata endpoints, internal APIs, or other services that are not intended to be exposed. The vulnerability does not require authentication beyond what is needed to initiate a migration [1][2].

Mitigation

Vikunja version 2.2.1 patches the issue by replacing the plain http.Client{} with a centralized SSRF-safe HTTP client (utils.NewSSRFSafeHTTPClient()) that includes proper protections [3][4]. Users are strongly advised to update to 2.2.1 or later. The fix also introduced a centralized SSRF protection layer covering all outgoing HTTP requests, including webhooks, migrations, avatar downloads, and background image fetches [3].

AI Insight generated on May 18, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
code.vikunja.io/apiGo
< 2.2.12.2.1

Affected products

2
  • Vikunja/Vikunjallm-fuzzy
    Range: <2.2.1
  • go-vikunja/vikunjav5
    Range: < 2.2.1

Patches

1
93297742236e

fix: prevent SSRF via migration file attachment URLs (GHSA-g66v-54v9-52pr)

https://github.com/go-vikunja/vikunjakolaenteMar 23, 2026via ghsa
2 files changed · +6 4
  • pkg/modules/migration/helpers.go+4 4 modified
    @@ -47,8 +47,8 @@ func DownloadFileWithHeaders(url string, headers http.Header) (buf *bytes.Buffer
     		}
     	}
     
    -	hc := http.Client{}
    -	resp, err := hc.Do(req) // #nosec G704 -- URL is from migration provider API
    +	hc := utils.NewSSRFSafeHTTPClient()
    +	resp, err := hc.Do(req)
     	if err != nil {
     		return nil, err
     	}
    @@ -66,7 +66,7 @@ func DoPost(url string, form url.Values) (resp *http.Response, err error) {
     
     // DoGetWithHeaders makes an HTTP GET request with custom headers
     func DoGetWithHeaders(urlStr string, headers map[string]string) (resp *http.Response, err error) {
    -	hc := http.Client{}
    +	hc := utils.NewSSRFSafeHTTPClient()
     
     	err = utils.RetryWithBackoff("HTTP GET "+urlStr, func() error {
     		req, reqErr := http.NewRequestWithContext(context.Background(), http.MethodGet, urlStr, nil)
    @@ -108,7 +108,7 @@ func DoGetWithHeaders(urlStr string, headers map[string]string) (resp *http.Resp
     
     // DoPostWithHeaders does an api request and allows to pass in arbitrary headers
     func DoPostWithHeaders(urlStr string, form url.Values, headers map[string]string) (resp *http.Response, err error) {
    -	hc := http.Client{}
    +	hc := utils.NewSSRFSafeHTTPClient()
     
     	err = utils.RetryWithBackoff("HTTP POST "+urlStr, func() error {
     		req, reqErr := http.NewRequestWithContext(context.Background(), http.MethodPost, urlStr, strings.NewReader(form.Encode()))
    
  • pkg/modules/migration/main_test.go+2 0 modified
    @@ -36,6 +36,8 @@ func TestMain(m *testing.M) {
     
     	// Set default config
     	config.InitDefaultConfig()
    +	// Allow non-routable IPs in tests so httptest.NewServer (127.0.0.1) works
    +	config.OutgoingRequestsAllowNonRoutableIPs.Set("true")
     
     	// Some tests use the file engine, so we'll need to initialize that
     	files.InitTests()
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.