Vikunja has SSRF via Todoist/Trello Migration File Attachment URLs that Allows Reading Internal Network Resources
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.
| Package | Affected versions | Patched versions |
|---|---|---|
code.vikunja.io/apiGo | < 2.2.1 | 2.2.1 |
Affected products
2- go-vikunja/vikunjav5Range: < 2.2.1
Patches
193297742236efix: prevent SSRF via migration file attachment URLs (GHSA-g66v-54v9-52pr)
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- github.com/advisories/GHSA-g66v-54v9-52prghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-33675ghsaADVISORY
- github.com/go-vikunja/vikunja/commit/93297742236e3d33af72c993e5da960db01d259eghsax_refsource_MISCWEB
- github.com/go-vikunja/vikunja/security/advisories/GHSA-g66v-54v9-52prghsax_refsource_CONFIRMWEB
- vikunja.io/changelog/vikunja-v2.2.2-was-releasedghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.