CVE-2026-56765
Vikunja - Unauthenticated Instance-Wide Data Breach via Link Share Hash Disclosure Chained with Cross-Project Attachment IDOR
Vikunja before 2.2.1 contains an authorization flaw where the LinkSharing.ReadAll endpoint exposes share hashes to users with read access, enabling permission escalation to admin-level shares. The GetTaskAttachment endpoint performs permission checks against user-supplied task IDs but fetches attachments by sequential ID without verifying ownership, allowing attackers to download and delete all file attachments across all projects instance-wide.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
9.3
Vikunja - Unauthenticated Instance-Wide Data Breach via Link Share Hash Disclosure Chained with Cross-Project Attachment IDOR
Vikunja before 2.2.1 contains an authorization flaw where the LinkSharing.ReadAll endpoint exposes share hashes to users with read access, enabling permission escalation to admin-level shares. The GetTaskAttachment endpoint performs permission checks against user-supplied task IDs but fetches attachments by sequential ID without verifying ownership, allowing attackers to download and delete all file attachments across all projects instance-wide.
- Record
CVE-2026-56765- CVSS 4.0
- 9.3 Critical
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - CVSS 3.1
- 9.8 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-639
- Updated
- 2026-11-02
EUVDEUVD-2026-42890
9.3
Vikunja before 2.2.1 contains an authorization flaw where the LinkSharing.ReadAll endpoint exposes share hashes to users with read access, enabling permission escalation to admin-level shares. The GetTaskAttachment endpoint performs permission checks against user-supplied task IDs but fetches attachments by sequential ID without verifying ownership, allowing attackers to download and delete all file attachments across all projects instance-wide.
- Record
EUVD-2026-42890- CVSS 4.0
- 9.3 Critical
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-2pv8-4c52-mf8j
9.1
Vikunja: Unauthenticated Instance-Wide Data Breach via Link Share Hash Disclosure Chained with Cross-Project Attachment IDOR
Summary
Two independently-exploitable authorization flaws in Vikunja can be chained to allow an unauthenticated attacker to download and delete every file attachment across all projects in a Vikunja instance. The ReadAll endpoint for link shares exposes share hashes (including admin-level shares) to any user with read access, enabling permission escalation. The task attachment ReadOne/GetTaskAttachment endpoint performs permission checks against a user-supplied task ID but fetches the attachment by its own sequential ID without verifying the attachment belongs to that task, enabling cross-project file access.
Details
Vulnerability 1: Link Share Hash Disclosure (Permission Escalation Entry Point)
Tracked in https://github.com/go-vikunja/vikunja/security/advisories/GHSA-8hp8-9fhr-pfm9
The LinkSharing.ReadAll() method in pkg/models/link_sharing.go:228-287 returns all link shares for a project, including the Hash field:
// pkg/models/link_sharing.go:46-50
type LinkSharing struct {
ID int64 `xorm:"bigint autoincr not null unique pk" json:"id" param:"share"`
Hash string `xorm:"varchar(40) not null unique" json:"hash" param:"hash"` // ← exposed in JSON
// ...
}
The ReadAll clears passwords but not hashes:
// pkg/models/link_sharing.go:272-277
for _, s := range shares {
if sharedBy, has := users[s.SharedByID]; has {
s.SharedBy = sharedBy
}
s.Password = "" // ← password cleared, but hash remains
}
A link share user with read-only access can call GET /api/v1/projects/:project/shares (routed at pkg/routes/routes.go:483) to discover all shares, then authenticate with an admin-level share hash.
Vulnerability 2: Cross-Project Attachment IDOR (Data Exfiltration)
Tracked in https://github.com/go-vikunja/vikunja/security/advisories/GHSA-jfmm-mjcp-8wq2
The GetTaskAttachment handler in pkg/routes/api/v1/task_attachment.go:156-186 performs the permission check against the task ID supplied in the URL:
// pkg/models/task_attachment_permissions.go:25-28
func (ta *TaskAttachment) CanRead(s *xorm.Session, a web.Auth) (bool, int, error) {
t := &Task{ID: ta.TaskID} // ← ta.TaskID from URL parameter
return t.CanRead(s, a) // ← checks if user can read THIS task
}
But ReadOne fetches the attachment by its own ID, ignoring the task:
// pkg/models/task_attachment.go:110-111
func (ta *TaskAttachment) ReadOne(s *xorm.Session, _ web.Auth) (err error) {
exists, err := s.Where("id = ?", ta.ID).Get(ta) // ← fetches by attachment ID only
// ta.TaskID is now overwritten with the ACTUAL task ID from the database
// But the permission check already passed using the attacker-controlled task ID
This means: specify a task you CAN access, but an attachment ID from a different project → permission check passes, wrong attachment is returned.
The Chain
Link share URL (public)
→ POST /shares/{hash}/auth (get JWT)
→ GET /projects/{id}/shares (discover admin share hash)
→ POST /shares/{admin_hash}/auth (escalate to admin)
→ GET /projects/{id}/tasks (find any accessible task ID)
→ GET /tasks/{accessible_task}/attachments/{1..N} (enumerate ALL attachments)
→ DELETE /tasks/{accessible_task}/attachments/{1..N} (destroy ALL attachments)
PoC
Prerequisites: A Vikunja instance with at least one link share (any permission level). The attacker only needs the link share URL.
VIKUNJA="http://localhost:3456/api/v1"
# Step 1: Authenticate with a known read-only link share hash
# (Link share URLs look like: https://instance/share/HASH_HERE)
SHARE_HASH="read-only-share-hash"
TOKEN=$(curl -s -X POST "$VIKUNJA/shares/$SHARE_HASH/auth" \
-H "Content-Type: application/json" \
-d '{}' | jq -r '.token')
echo "Got JWT: $TOKEN"
# Step 2: Discover all link shares for the project (including admin shares)
PROJECT_ID=1 # from the link share JWT claims
SHARES=$(curl…
- Record
GHSA-2pv8-4c52-mf8j- CVSS 3.1
- 9.1 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N - Weakness
- CWE-639
- Updated
- 2026-11-02
GitHub AdvisoriesGHSA-pg6g-jf8c-49p7
9.3
Vikunja before 2.2.1 contains an authorization flaw where the LinkSharing.ReadAll endpoint...
Vikunja before 2.2.1 contains an authorization flaw where the LinkSharing.ReadAll endpoint exposes share hashes to users with read access, enabling permission escalation to admin-level shares. The GetTaskAttachment endpoint performs permission checks against user-supplied task IDs but fetches attachments by sequential ID without verifying ownership, allowing attackers to download and delete all file attachments across all projects instance-wide.
- Record
GHSA-pg6g-jf8c-49p7- CVSS 4.0
- 9.3 Critical
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 9.8 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-639
- Updated
- 2026-11-02
NVD
9.3
Vikunja before 2.2.1 contains an authorization flaw where the LinkSharing.ReadAll endpoint exposes share hashes to users with read access, enabling permission escalation to admin-level shares. The GetTaskAttachment endpoint performs permission checks against user-supplied task IDs but fetches attachments by sequential ID without verifying ownership, allowing attackers to download and delete all file attachments across all projects instance-wide.
- Record
CVE-2026-56765- CVSS 4.0
- 9.3 Critical
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 9.8 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-639
- Updated
- 2026-11-02
OSV
9.3
Vikunja - Unauthenticated Instance-Wide Data Breach via Link Share Hash Disclosure Chained with Cross-Project Attachment IDOR
Vikunja before 2.2.1 contains an authorization flaw where the LinkSharing.ReadAll endpoint exposes share hashes to users with read access, enabling permission escalation to admin-level shares. The GetTaskAttachment endpoint performs permission checks against user-supplied task IDs but fetches attachments by sequential ID without verifying ownership, allowing attackers to download and delete all file attachments across all projects instance-wide.
- Record
CVE-2026-56765- CVSS 4.0
- 9.3 Critical
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - Weakness
- CWE-639
- Updated
- 2026-11-02
OSVGHSA-2pv8-4c52-mf8j
9.1
Vikunja: Unauthenticated Instance-Wide Data Breach via Link Share Hash Disclosure Chained with Cross-Project Attachment IDOR
Summary
Two independently-exploitable authorization flaws in Vikunja can be chained to allow an unauthenticated attacker to download and delete every file attachment across all projects in a Vikunja instance. The ReadAll endpoint for link shares exposes share hashes (including admin-level shares) to any user with read access, enabling permission escalation. The task attachment ReadOne/GetTaskAttachment endpoint performs permission checks against a user-supplied task ID but fetches the attachment by its own sequential ID without verifying the attachment belongs to that task, enabling cross-project file access.
Details
Vulnerability 1: Link Share Hash Disclosure (Permission Escalation Entry Point)
Tracked in https://github.com/go-vikunja/vikunja/security/advisories/GHSA-8hp8-9fhr-pfm9
The LinkSharing.ReadAll() method in pkg/models/link_sharing.go:228-287 returns all link shares for a project, including the Hash field:
// pkg/models/link_sharing.go:46-50
type LinkSharing struct {
ID int64 `xorm:"bigint autoincr not null unique pk" json:"id" param:"share"`
Hash string `xorm:"varchar(40) not null unique" json:"hash" param:"hash"` // ← exposed in JSON
// ...
}
The ReadAll clears passwords but not hashes:
// pkg/models/link_sharing.go:272-277
for _, s := range shares {
if sharedBy, has := users[s.SharedByID]; has {
s.SharedBy = sharedBy
}
s.Password = "" // ← password cleared, but hash remains
}
A link share user with read-only access can call GET /api/v1/projects/:project/shares (routed at pkg/routes/routes.go:483) to discover all shares, then authenticate with an admin-level share hash.
Vulnerability 2: Cross-Project Attachment IDOR (Data Exfiltration)
Tracked in https://github.com/go-vikunja/vikunja/security/advisories/GHSA-jfmm-mjcp-8wq2
The GetTaskAttachment handler in pkg/routes/api/v1/task_attachment.go:156-186 performs the permission check against the task ID supplied in the URL:
// pkg/models/task_attachment_permissions.go:25-28
func (ta *TaskAttachment) CanRead(s *xorm.Session, a web.Auth) (bool, int, error) {
t := &Task{ID: ta.TaskID} // ← ta.TaskID from URL parameter
return t.CanRead(s, a) // ← checks if user can read THIS task
}
But ReadOne fetches the attachment by its own ID, ignoring the task:
// pkg/models/task_attachment.go:110-111
func (ta *TaskAttachment) ReadOne(s *xorm.Session, _ web.Auth) (err error) {
exists, err := s.Where("id = ?", ta.ID).Get(ta) // ← fetches by attachment ID only
// ta.TaskID is now overwritten with the ACTUAL task ID from the database
// But the permission check already passed using the attacker-controlled task ID
This means: specify a task you CAN access, but an attachment ID from a different project → permission check passes, wrong attachment is returned.
The Chain
Link share URL (public)
→ POST /shares/{hash}/auth (get JWT)
→ GET /projects/{id}/shares (discover admin share hash)
→ POST /shares/{admin_hash}/auth (escalate to admin)
→ GET /projects/{id}/tasks (find any accessible task ID)
→ GET /tasks/{accessible_task}/attachments/{1..N} (enumerate ALL attachments)
→ DELETE /tasks/{accessible_task}/attachments/{1..N} (destroy ALL attachments)
PoC
Prerequisites: A Vikunja instance with at least one link share (any permission level). The attacker only needs the link share URL.
VIKUNJA="http://localhost:3456/api/v1"
# Step 1: Authenticate with a known read-only link share hash
# (Link share URLs look like: https://instance/share/HASH_HERE)
SHARE_HASH="read-only-share-hash"
TOKEN=$(curl -s -X POST "$VIKUNJA/shares/$SHARE_HASH/auth" \
-H "Content-Type: application/json" \
-d '{}' | jq -r '.token')
echo "Got JWT: $TOKEN"
# Step 2: Discover all link shares for the project (including admin shares)
PROJECT_ID=1 # from the link share JWT claims
SHARES=$(curl…
- Record
GHSA-2pv8-4c52-mf8j- CVSS 3.1
- 9.1 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N - Weakness
- CWE-639
- Updated
- 2026-11-02
OSVGO-2026-4855 No score
Vikunja: Unauthenticated Instance-Wide Data Breach via Link Share Hash Disclosure Chained with Cross-Project Attachment IDOR in code.vikunja.io/api
Vikunja: Unauthenticated Instance-Wide Data Breach via Link Share Hash Disclosure Chained with Cross-Project Attachment IDOR in code.vikunja.io/api.
NOTE: The source advisory for this report contains additional versions that could not be automatically mapped to standard Go module versions.
(If this is causing false-positive reports from vulnerability scanners, please suggest an edit to the report.)
The additional affected modules and versions are: code.vikunja.io/api before v2.2.1.
- Record
GO-2026-4855- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
code.vikunja.io/apiGo |
through 2.2.0 | 2.2.1 |
code.vikunja.io/apiGo |
before 2.2.1 | 2.2.1 |
code.vikunja.io/apiGo |
All versions | None known |
History
| Recorded | Changed | Sources |
|---|---|---|
| aliases, products | EUVD | |
| first indexed | CVE List, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-56765 is a critical vulnerability (CVSS 9.3) in Go-vikunja Vikunja, published March 26, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.51%, the 43rd percentile. Fixed in code.vikunja.io/api 2.2.1.
References
github.com/go-vikunja/vikunja/security/advisories/GHSA-2pv8-4c52-mf8j
vulncheck.com/advisories/vikunja-unauthenticated-instance-wide-data-breach-via-link-share-hash-disclosure-chained-with-cross-project-attachment-idor
github.com/go-vikunja/vikunja/security/advisories/GHSA-8hp8-9fhr-pfm9
github.com/go-vikunja/vikunja/security/advisories/GHSA-jfmm-mjcp-8wq2
vikunja.io/changelog/vikunja-v2.2.2-was-released
github.com/advisories/GHSA-2pv8-4c52-mf8j
Left out here: the rest of 2 source descriptions. The JSON record has them.