Vulnerabilities in pkg:golang/code.vikunja.io/api
PACKAGEGHSA-m687-p538-r5hp is a HIGH permissive cross-domain security policy trusts vulnerability (CWE-942: Permissive Cross-domain Security Policy with Untrusted Domains) affecting Vikunja libraries in the Go ecosystem. The issue involves permissive cross-domain security policy trusts every localhost origin which should not be trusted. Remediation is available in the latest vendor maintenance releases.
pkg:golang/code.vikunja.io/api
Vulnerability advisories affecting package pkg:golang/code.vikunja.io/api. Select an advisory below to view technical details or fixes.
| Advisory ID | CVE / NVD | Severity | Summary |
|---|---|---|---|
| GHSA-m687-p538-r5hp | - | HIGH | Vikunja: Permissive Cross-domain Security Policy trusts every localhost origin which should not be trusted |
| GHSA-fmmf-xq98-g327 | - | MODERATE | Vikunja: Write-level project members can delete admin-tier link shares through an unloaded permission check |
| GHSA-pjr3-86v4-5p7w | - | MODERATE | Vikunja: Explicit lower-permission share on a sub-project is silently overridden by an inherited parent permission (broken access control / privilege-management regression in v2.6.0) |
| GHSA-hjx8-qv73-f7cm | - | MODERATE | Vikunja: Webhooks and link shares survive every revocation path, so a removed collaborator keeps a live feed |
| GHSA-fprf-r6rv-xg99 | - | MODERATE | Vikunja: Saved filter creation with an empty filter string recalculates task positions across all tenants |
| GHSA-4hv6-xc92-j86g | - | MODERATE | Vikunja: WebSocket authentication ignores server-side session state, so revoked sessions keep receiving live pushes |
| GHSA-w2ch-4xgr-22ww | - | LOW | Vikunja: Task relation deletion does not check read access to the other task, allowing cross-project relation removal |
| GHSA-8wvg-r2j4-3737 | - | MODERATE | Vikunja: Assignee email addresses disclosed to read-only project members via the task assignees endpoint |
| GHSA-3hc7-r24j-rpwc | - | MODERATE | Vikunja: Cross-project task disclosure through subtask expansion |
| GHSA-g38j-7v97-x298 | - | MODERATE | Vikunja: CalDAV relation creation bypasses TaskRelation.CanCreate, allowing an unauthorized write into any task by known UID |
| GHSA-wq92-8x3r-fm38 | CVE-2026-91970 | HIGH | Vikunja: Planka migration retains an unbounded aggregate of attacker-served attachments and can OOM the API |
| GHSA-c2g7-39fr-cp8q | - | HIGH | Duplicate Advisory: Vikunja: Planka migration retains an unbounded aggregate of attacker-served attachments and can OOM the API |
| GHSA-pqf9-h8g4-8gmh | CVE-2026-91969 | HIGH | Vikunja: Unbounded CSV row cardinality permits API process termination |
| GHSA-55p4-8j34-jv53 | - | HIGH | Duplicate Advisory: Vikunja: Unbounded CSV row cardinality permits API process termination |
| GHSA-xxc3-xpmc-vmvr | CVE-2026-91968 | HIGH | Vikunja: Unbounded nested task-filter recursion permits API process termination |
| GHSA-jfw3-2gcf-23r5 | - | HIGH | Duplicate Advisory: Vikunja: Unbounded nested task-filter recursion permits API process termination |
| GHSA-w7jp-mf2v-8342 | CVE-2026-91979 | HIGH | Vikunja: Denial of service via decompression bomb in the data import |
| GHSA-vfxw-3x8p-2vjr | CVE-2026-91981 | MODERATE | Vikunja: Link-share token can enumerate users through the v2 API |
| GHSA-vcgv-7rvm-m3vp | - | MODERATE | Duplicate Advisory: Vikunja: Link-share token can enumerate users through the v2 API |
| GHSA-39p5-2wrr-xh29 | CVE-2026-91980 | MODERATE | Vikunja: Any user can enumerate every team and its members by attaching arbitrary teams to a throwaway project |
| GHSA-2922-qgfj-pr7v | - | MODERATE | Duplicate Advisory: Vikunja: Any user can enumerate every team and its members by attaching arbitrary teams to a throwaway project |
| GHSA-4vh2-39rq-rq8j | CVE-2026-91971 | HIGH | Vikunja: Unbounded image decode on avatar and project-background uploads enables decode/resize amplification |
| GHSA-69rj-q3v9-vffp | - | HIGH | Duplicate Advisory: Vikunja: Unbounded image decode on avatar and project-background uploads enables decode/resize amplification |
| GHSA-m469-88xx-8rx2 | CVE-2026-91973 | MODERATE | Vikunja: CalDAV and feeds BasicAuth endpoints have no rate limit, bypassing the anti-brute-force floor on account passwords |
| GHSA-p2vv-wrh8-x466 | - | HIGH | Duplicate Advisory: Vikunja: CalDAV and feeds BasicAuth endpoints have no rate limit, bypassing the anti-brute-force floor on account passwords |
| GHSA-9rg3-v78m-26q8 | CVE-2026-91983 | MODERATE | Vikunja: API token scopes bypassed via task expand parameter (comments, reactions, time entry counts) |
| GHSA-phph-c358-5mwm | - | MODERATE | Duplicate Advisory: Vikunja: API token scopes bypassed via task expand parameter (comments, reactions, time entry counts) |
| GHSA-w39f-h553-h2mx | CVE-2026-91984 | MODERATE | Vikunja: Cross-tenant task-position rows can be injected into arbitrary project views via the unvalidated project_view_id in the task position endpoint (v1 and v2) |
| GHSA-ccgq-fx7h-2v4c | - | MODERATE | Duplicate Advisory: Vikunja: Cross-tenant task-position rows can be injected into arbitrary project views via the unvalidated project_view_id in the task position endpoint (v1 and v2) |
| GHSA-qfwc-vx6f-3g6g | CVE-2026-91985 | HIGH | Vikunja: Read-only project members can obtain any link share's access hash via the single-share read endpoint (v1 and v2) and escalate to the share's permission level |
| GHSA-37rx-7pj5-p885 | - | HIGH | Duplicate Advisory: Vikunja: Read-only project members can obtain any link share's access hash via the single-share read endpoint (v1 and v2) and escalate to the share's permission level |
| GHSA-88f6-4rjv-x774 | CVE-2026-91982 | MODERATE | Vikunja: TOTP secret is readable after enrollment, no step-up auth |
| GHSA-jmr8-r558-3jhx | - | MODERATE | Duplicate Advisory: Vikunja: TOTP secret is readable after enrollment, no step-up auth |
| GHSA-6rvj-qwjf-3m4q | CVE-2026-91972 | HIGH | Vikunja: Every /api/v2 pre-auth endpoint is unthrottled on a stock install while its /api/v1 twin is rate limited |
| GHSA-r6w9-259g-gwrv | CVE-2026-62376 | HIGH | Vikunja: Plaintext storage of password-reset/email-confirm tokens in database enables account takeover on DB read access |
| GHSA-xv7q-fvmc-jx96 | CVE-2026-62367 | HIGH | Vikunja: OIDC email-fallback account linking ignores email_verified, enabling local-account takeover |
| GHSA-32r8-5843-4qw2 | CVE-2026-76216 | HIGH | Vikunja: Link-share principal-type confusion enables cross-account team removal, bot takeover, and roster disclosure |
| GHSA-9xwc-vwww-qqmw | - | HIGH | Duplicate Advisory: Vikunja: Link-share principal-type confusion enables cross-account team removal, bot takeover, and roster disclosure |
| GHSA-rj9j-8772-4h6c | CVE-2026-68582 | CRITICAL | Vikunja: Link-share token reads any tenant's kanban buckets and enumerates usernames/IDs instance-wide (BOLA) |
| GHSA-p4r4-8cxw-pjx7 | - | CRITICAL | Duplicate Advisory: Vikunja: Link-share token reads any tenant's kanban buckets and enumerates usernames/IDs instance-wide (BOLA) |
| GHSA-vvcv-vpph-h844 | CVE-2026-68581 | HIGH | Vikunja: Link-share principal ID collision allows cross-account API token issuance and management |
| GHSA-9jrx-vmh8-c6xw | - | HIGH | Duplicate Advisory: Vikunja: Link-share principal ID collision allows cross-account API token issuance and management |
| GHSA-v3p6-34mc-hj7v | CVE-2026-57458 | HIGH | Vikunja: Scoped API token can mint unrestricted OAuth session credentials |
| GHSA-569v-q83c-3j3g | CVE-2026-55067 | MODERATE | Vikunja vulnerable to authenticated cross-tenant kanban-bucket relocation via `project_view_id` mass-assignment |
| GHSA-5pg6-m483-7vrg | CVE-2026-55066 | HIGH | Vikunja has cross-tenant IDOR in kanban move-task endpoint via unauthorized body task_id |
| GHSA-gg93-x632-9ccv | CVE-2026-55065 | HIGH | Vikunja vulnerable to Improper Authorization and Authorization Bypass Through User-Controlled Key |
| GHSA-44v6-7fxq-vgf4 | CVE-2026-55064 | MODERATE | Vikunja has an incomplete fix for CVE-2026-35595: Write-only user can detach shared project from parent hierarchy via parent_project_id=0 |
| GHSA-f27p-pw2p-9pr4 | CVE-2026-54766 | MODERATE | Vikunja has a project duplication bypasses write-permission check on the target parent project |
| GHSA-hj5c-mhh2-g7jq | CVE-2026-35596 | MODERATE | Vikunja has Broken Access Control on Label Read via SQL Operator Precedence Bug |
| GHSA-fgfv-pv97-6cmj | CVE-2026-35597 | MODERATE | Vikunja Vulnerable to TOTP Brute-Force Due to Non-Functional Account Lockout |
| GHSA-96q5-xm3p-7m84 | CVE-2026-35594 | MODERATE | Vikunja: Link Share JWT tokens remain valid for 72 hours after share deletion or permission downgrade |
| GHSA-8jvc-mcx6-r4cg | CVE-2026-34727 | HIGH | Vikunja has TOTP Two-Factor Authentication Bypass via OIDC Login Path |
| GHSA-2g7h-7rqr-9p4r | CVE-2026-35601 | MODERATE | Vikunja has iCalendar Property Injection via CRLF in CalDAV Task Output |
| GHSA-2vq4-854f-5c72 | CVE-2026-35595 | HIGH | Vikunja vulnerable to Privilege Escalation via Project Reparenting |
| GHSA-v479-vf79-mg83 | CVE-2026-40103 | MODERATE | Vikunja: Scoped API tokens with projects.background permission can delete project backgrounds |
| GHSA-qh78-rvg3-cv54 | CVE-2026-35602 | MODERATE | Vikunja has File Size Limit Bypass via Vikunja Import |
| GHSA-45q4-x4r9-8fqj | CVE-2026-35600 | MODERATE | Vikunja has HTML Injection via Task Titles in Overdue Email Notifications |
| GHSA-r4fg-73rc-hhh7 | CVE-2026-35599 | MODERATE | Vikunja has Algorithmic Complexity DoS in Repeating Task Handler |
| GHSA-48ch-p4gq-x46x | CVE-2026-35598 | MODERATE | Vikunja Missing Authorization on CalDAV Task Read |
| GHSA-8hp8-9fhr-pfm9 | CVE-2026-33680 | HIGH | Vikjuna: Link Share Hash Disclosure via ReadAll Endpoint Enables Permission Escalation |
| GHSA-g9xj-752q-xh63 | CVE-2026-33679 | MODERATE | Vikjuna Bypasses Webhook SSRF Protections During OpenID Connect Avatar Download |
| GHSA-2pv8-4c52-mf8j | - | CRITICAL | Vikunja: Unauthenticated Instance-Wide Data Breach via Link Share Hash Disclosure Chained with Cross-Project Attachment IDOR |
| GHSA-f95f-77jx-fcjc | CVE-2026-33700 | MODERATE | Vikunja has a Link Share Delete IDOR — Missing Project Ownership Check Allows Cross-Project Link Share Deletion |
| GHSA-jfmm-mjcp-8wq2 | CVE-2026-33678 | HIGH | Vikjuna: IDOR in Task Attachment ReadOne Allows Cross-Project File Access and Deletion |
| GHSA-7c2g-p23p-4jg3 | CVE-2026-33677 | MODERATE | Vikjuna: Webhook BasicAuth Credentials Exposed to Read-Only Project Collaborators via API |
| GHSA-8cmm-j6c4-rr8v | CVE-2026-33676 | MODERATE | Vikunja has Cross-Project Information Disclosure via Task Relations — Missing Authorization Check on Related Task Read |
| GHSA-g66v-54v9-52pr | CVE-2026-33675 | MODERATE | Vikunja has SSRF via Todoist/Trello Migration File Attachment URLs that Allows Reading Internal Network Resources |
| GHSA-94xm-jj8x-3cr4 | CVE-2026-33668 | HIGH | Vikunja Allows Disabled/Locked User Accounts to Authenticate via API Tokens, CalDAV, and OpenID Connect |
| GHSA-wc83-79hj-hpmq | CVE-2026-33474 | MODERATE | Vikunja Affected by DoS via Image Preview Generation |
| GHSA-vq4q-79hh-q767 | CVE-2026-33316 | HIGH | Vikunja’s Improper Access Control Enables Bypass of Administrator-Imposed Account Disablement |
| GHSA-47cr-f226-r4pq | CVE-2026-33315 | MODERATE | Vikunja has a 2FA Bypass via Caldav Basic Auth |
| GHSA-mr3j-p26x-72x4 | CVE-2026-33313 | MODERATE | Vikunja has an IDOR in Task Comments Allows Reading Arbitrary Comments |
| GHSA-p747-qc5p-773r | CVE-2026-33473 | MODERATE | Vikunja has TOTP Reuse During Validity Window |
| GHSA-m547-hp4w-j6jx | CVE-2026-29794 | MODERATE | Vikunja has a Rate-Limit Bypass for Unauthenticated Users via Spoofed Headers |
| GHSA-564f-wx8x-878h | CVE-2026-33312 | MODERATE | Vikunja read-only users can delete project background images via broken object-level authorization |
| GHSA-rfjg-6m84-crj2 | CVE-2026-28268 | CRITICAL | Vikunja Vulnerable to Account Takeover via Password Reset Token Reuse |
| GHSA-7jp5-298q-jg98 | CVE-2026-27616 | HIGH | Vikunja: Stored XSS via Unsanitized SVG Attachment Upload Leads to Token Exposure |
| GHSA-3ccg-x393-96v8 | CVE-2026-27575 | CRITICAL | Vijkunja has Weak Password Policy Combined with Persistent Sessions After Password Change |
| GHSA-4qgr-4h56-8895 | CVE-2026-27116 | MODERATE | Vikunja has Reflected HTML Injection via filter Parameter in its Projects Module |
| GHSA-42wg-38gx-85rh | CVE-2026-27819 | HIGH | Vikunja has Path Traversal in CLI Restore |
| GHSA-m4g2-2q66-vc9v | CVE-2026-25935 | HIGH | Vikunja Vulnerable to XSS Via Task Preview |
GHSA-m687-p538-r5hp at a Glance
How to Fix GHSA-m687-p538-r5hp
To remediate this vulnerability, upgrade all affected Vikunja dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
Upgrade code.vikunja.io/api to Latest secure release
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
inspect dependencies for code.vikunja.io/api
How to Check if You Are Affected
To determine whether your application is affected by GHSA-m687-p538-r5hp, inspect your project dependencies for Vikunja:
inspect dependencies for code.vikunja.io/api
Analyze the terminal output to locate any version of Vikunja in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than the patched release), your application is affected.
Note: Verify declared build manifests and deployed runtime container environments.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-942: Permissive Cross-domain Security Policy with Untrusted Domains, where the product uses a web-client protection mechanism such as a content security policy (csp) or cross-domain policy file, but the policy includes untrusted domains with which the web client is allowed to communicate. In Vikunja, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
GHSA-m687-p538-r5hp Affected Vikunja Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
code.vikunja.io/api
|
Go |
≥ 2.2.0
≤ 2.6.0
|
|
References
Frequently Asked Questions
What is GHSA-m687-p538-r5hp?
Which Vikunja versions are affected?
What version fixes GHSA-m687-p538-r5hp?
Is code.vikunja.io/api affected?
What CWE is associated with GHSA-m687-p538-r5hp?
How can I check Go dependencies for GHSA-m687-p538-r5hp?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-m687-p538-r5hp",
"modified" : "2026-10-09T20:57:50Z",
"published" : "2026-10-09T20:57:50Z",
"aliases" : [ ],
"summary" : "Vikunja: Permissive Cross-domain Security Policy trusts every localhost origin which should not be trusted",
"details" : "## Summary\n\nVikunja ships with `cors.origins` defaulting to `http://127.0.0.1:*` and `http://localhost:*`, and sends `Access-Control-Allow-Credentials: true`, so a page served from any port on the user's own machine may make credentialed cross-origin requests to the API and read the responses. The mandatory `service.publicurl` is appended to that default list rather than replacing it, so a fully configured production deployment still trusts every localhost origin. Combined with the token refresh endpoint, which authenticates with the `vikunja_refresh_token` cookie and returns a bearer JWT in the response body, one `fetch()` from such a page yields a working access token for whoever is logged in, and from there the whole account.\n\n## Vulnerability Details\n\n`cors.enable` defaults to true and `cors.origins` defaults to the two localhost wildcards:\n\nhttps://github.com/go-vikunja/vikunja/blob/a881ac39eecd07575a5aede8e74727c28d5fd578/pkg/config/config.go#L495-L497\n\nThe middleware is registered with `AllowCredentials: true` and an `UnsafeAllowOriginFunc` that implements the port wildcard through `matchCORSOrigin`, since Echo v5 will not accept a wildcard port itself:\n\nhttps://github.com/go-vikunja/vikunja/blob/a881ac39eecd07575a5aede8e74727c28d5fd578/pkg/routes/routes.go#L263-L281\n\nThe detail that turns a development convenience into a production exposure is the last line of configuration handling. Enabling CORS without a public URL is a fatal error, so every deployment sets one, and that value is *appended* to the origin list rather than substituted for it:\n\nhttps://github.com/go-vikunja/vikunja/blob/a881ac39eecd07575a5aede8e74727c28d5fd578/pkg/config/config.go#L828-L830\n\nAn operator who configures nothing but their own hostname therefore ends up allowing three origins with credentials: their site, and any port on `localhost` and `127.0.0.1`. There is no supported configuration in which the localhost entries are quietly dropped, and nothing in the logs distinguishes the intended origin from the inherited ones.\n\nThe escalation path is the refresh endpoint. It is deliberately unauthenticated because it authenticates with the refresh cookie instead of a bearer token, and it returns the new access token in the JSON body:\n\nhttps://github.com/go-vikunja/vikunja/blob/a881ac39eecd07575a5aede8e74727c28d5fd578/pkg/routes/api/v1/login.go#L129-L150\n\nThe cookie is `HttpOnly`, but that offers no protection here, because the attacking page never reads the cookie. It issues a credentialed request and the browser attaches the cookie itself. `SetRefreshTokenCookie` marks the cookie `SameSite=None` whenever the public URL is `https`, precisely so the cookie survives split-origin deployments, which is also what allows a cross-site send from a localhost page:\n\nhttps://github.com/go-vikunja/vikunja/blob/a881ac39eecd07575a5aede8e74727c28d5fd578/pkg/modules/auth/auth.go#L84-L104\n\nSo a single `fetch('https://vikunja.example.com/api/v1/user/token/refresh', {method: 'POST', credentials: 'include'})` from any page on any localhost port returns a bearer token for the logged-in user, and the CORS response headers permit the page to read it. The token carries the user's full API authority.\n\n## Proof of Concept\n\nThree files, built together in one directory and run with:\n\n[poc.zip](https://github.com/user-attachments/files/31917334/poc.zip)\n\n```\ndocker build -f Dockerfile -t poc . && docker run --rm poc\n```\n\n- `Dockerfile` builds Vikunja from commit `a881ac39eecd07575a5aede8e74727c28d5fd578` and bakes the reproducer in.\n- `poc.sh` is the entrypoint. It starts the application on sqlite with `service.publicurl` as the only setting configured, waits for the health check, and runs the exploit.\n- `exploit.py` registers a user, logs them in, then acts as a page on `http://localhost:31337`: it reads the refresh cookie attributes, sends the CORS preflight, makes the credentialed refresh request, and asks the API who the returned token belongs to.\n\nNothing is stubbed and no internal function is called; everything after startup is ordinary HTTP against the running application. In the output `[+]` lines are measured checks and `[*]` lines are commentary, so only the checks and the final verdict are evidence.\n\nA run against `a881ac39eecd07575a5aede8e74727c28d5fd578` prints:\n\n```\n[*] Vikunja built from commit a881ac39ee, sqlite, service.publicurl=https://vikunja.example.com.\n[*] service.publicurl is the only setting configured. cors.enable and cors.origins keep their defaults.\n\n[+] The victim logs in and the refresh cookie is issued SameSite=None; Secure, so it is sent cross-site.\n[+] A page on http://localhost:31337 is allowed to send credentials: Access-Control-Allow-Origin: http://localhost:31337, Access-Control-Allow-Credentials: true\n[+] That page reads the response of a credentialed refresh, which carries a bearer token: eyJhbGciOiJIUzI1NiIsInR5cCI6...\n[+] The token authenticates as: 'victim'\n\nEXPLOIT SUCCESSFUL\n```\n\n## Suggested Fix\n\nThe fix is for `service.publicurl` to replace the localhost defaults rather than extend them, so that configuring a deployment narrows the allowed origins instead of widening them. If the localhost entries are retained deliberately for desktop clients, they should not be combined with `AllowCredentials: true`, since it is the combination that allows a third-party origin to read authenticated responses.\n\n## Attribution\n\nThis vulnerability was found using Google's security automation tooling, abd triaged manually with manual report writing by Ada Logics. Please credit Google and Ada Logics in any advisories.",
"severity" : [ {
"type" : "CVSS_V4",
"score" : "CVSS:4.0/AV:L/AC:L/AT:P/PR:N/UI:P/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "Go",
"name" : "code.vikunja.io/api"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "2.2.0"
}, {
"last_affected" : "2.6.0"
} ]
} ]
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/go-vikunja/vikunja/security/advisories/GHSA-m687-p538-r5hp"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/go-vikunja/vikunja"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-942" ],
"severity" : "HIGH",
"github_reviewed" : true,
"github_reviewed_at" : "2026-10-09T20:57:50Z",
"nvd_published_at" : null
}
}