{"description":"Trending threats, MITRE ATT\u0026CK coverage, and detection metadata. Fed continuously.","favicon":"https://feed.craftedsignal.io/favicon-32x32.png","feed_url":"https://feed.craftedsignal.io/products/vikunja--2.2.0--2.6.0/feed.json","home_page_url":"https://feed.craftedsignal.io/","icon":"https://feed.craftedsignal.io/apple-touch-icon.png","items":[{"_cs_actors":[],"_cs_cpes":["cpe:2.3:a:vikunja:vikunja:*:*:*:*:*:*:*:*"],"_cs_cves":[],"_cs_exploited":false,"_cs_has_poc":false,"_cs_poc_references":[],"_cs_products":["Vikunja (\u003e= 2.2.0, \u003c= 2.6.0)","Vikunja (\u003e 2.5.0)","Vikunja (\u003c= 2.5.0)","Vikunja (\u003c= 2.3.0)"],"_cs_severities":["high"],"_cs_tags":["web-application","cors","privilege-escalation","account-takeover","denial-of-service","memory-exhaustion","vikunja","migration","resource-exhaustion","api","dos","web-vulnerability","credential-access","vulnerability"],"_cs_type":"advisory","_cs_vendors":["Vikunja"],"content_html":"\u003cp\u003eVikunja versions 2.2.0 through 2.6.0 are affected by a permissive Cross-Origin Resource Sharing (CORS) policy vulnerability. The application defaults to allowing \u003ccode\u003ehttp://127.0.0.1:*\u003c/code\u003e and \u003ccode\u003ehttp://localhost:*\u003c/code\u003e as trusted origins. Crucially, when an administrator configures the required \u003ccode\u003eservice.publicurl\u003c/code\u003e for production, this value is appended to - rather than replacing - the existing localhost defaults. Because the application enables \u003ccode\u003eAccess-Control-Allow-Credentials: true\u003c/code\u003e and marks refresh cookies as \u003ccode\u003eSameSite=None\u003c/code\u003e, any web page running on the victim's local machine (on any port) can send a credentialed request to the Vikunja API. An attacker can exploit this by forcing a victim's browser to perform a cross-origin \u003ccode\u003ePOST\u003c/code\u003e request to the \u003ccode\u003e/api/v1/user/token/refresh\u003c/code\u003e endpoint, which returns a valid bearer JWT in the response body. The resulting token grants the attacker full administrative or user authority over the victim's account.\u003c/p\u003e\n\u003ch2 id=\"attack-chain\"\u003eAttack Chain\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003eThe victim logs into their production Vikunja instance, resulting in a persistent \u003ccode\u003evikunja_refresh_token\u003c/code\u003e cookie being set with \u003ccode\u003eSameSite=None\u003c/code\u003e and \u003ccode\u003eSecure\u003c/code\u003e attributes.\u003c/li\u003e\n\u003cli\u003eThe victim visits a malicious or compromised website running on any local port (e.g., \u003ccode\u003ehttp://localhost:31337\u003c/code\u003e).\u003c/li\u003e\n\u003cli\u003eThe malicious site initiates a \u003ccode\u003efetch()\u003c/code\u003e request to the victim's authenticated Vikunja instance, specifically targeting \u003ccode\u003ePOST /api/v1/user/token/refresh\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eThe victim's browser, observing the \u003ccode\u003eAccess-Control-Allow-Credentials: true\u003c/code\u003e header returned by the Vikunja server, attaches the \u003ccode\u003evikunja_refresh_token\u003c/code\u003e cookie to the cross-origin request.\u003c/li\u003e\n\u003cli\u003eThe Vikunja server validates the cookie, processes the request as a legitimate refresh attempt, and returns a JSON response containing a new valid bearer JWT.\u003c/li\u003e\n\u003cli\u003eThe malicious site receives the response, including the bearer token, due to the permissive \u003ccode\u003eAccess-Control-Allow-Origin\u003c/code\u003e header matching the localhost origin.\u003c/li\u003e\n\u003cli\u003eThe attacker uses the intercepted bearer token to authenticate against the Vikunja API as the victim, achieving full account takeover.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"impact\"\u003eImpact\u003c/h2\u003e\n\u003cp\u003eSuccessful exploitation results in total account compromise, granting an attacker full access to the victim's data, tasks, and administrative functions within the Vikunja instance. The impact is significant for organizations relying on Vikunja for sensitive task management, particularly where administrative or privileged user accounts are targeted via local browser-based vectors.\u003c/p\u003e\n\u003ch2 id=\"recommendation\"\u003eRecommendation\u003c/h2\u003e\n\u003cp\u003eDetection and mitigation should focus on identifying unauthorized access patterns and hardening the CORS configuration.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eUpgrade Vikunja to a version where \u003ccode\u003eservice.publicurl\u003c/code\u003e correctly overrides default localhost origins.\u003c/li\u003e\n\u003cli\u003eAudit web server logs for requests to \u003ccode\u003e/api/v1/user/token/refresh\u003c/code\u003e originating from unexpected \u003ccode\u003eOrigin\u003c/code\u003e headers, specifically those targeting loopback IP addresses or local ports.\u003c/li\u003e\n\u003cli\u003eImplement strict CORS policies on the reverse proxy or web server layer in front of Vikunja to explicitly whitelist only authorized production domains and strip unauthorized localhost origins from the \u003ccode\u003eAccess-Control-Allow-Origin\u003c/code\u003e header.\u003c/li\u003e\n\u003c/ul\u003e\n","date_modified":"2026-10-09T21:25:11Z","date_published":"2026-10-09T21:23:47Z","id":"https://feed.craftedsignal.io/briefs/2026-10-vikunja-cors-misconfiguration/","summary":"Vikunja versions 2.2.0 through 2.6.0 contain a CORS misconfiguration that implicitly trusts all localhost ports, allowing local attackers to retrieve valid bearer tokens via credentialed cross-origin requests.","title":"Vikunja Permissive CORS Policy Leading to Account Compromise","url":"https://feed.craftedsignal.io/briefs/2026-10-vikunja-cors-misconfiguration/"}],"language":"en","title":"CraftedSignal Threat Feed - Vikunja (\u003e= 2.2.0, \u003c= 2.6.0)","version":"https://jsonfeed.org/version/1.1"}