Mar 26, 2026·6 min read·3 visits
Chaining an authorization bypass in the link-sharing API and an IDOR in the attachment handler allows an attacker with a read-only link to extract administrative tokens and access arbitrary files across the entire Vikunja instance.
A critical vulnerability chain in the Vikunja task management platform allows unauthenticated or minimally authenticated attackers to perform an instance-wide data breach. By combining a link-share hash disclosure (CVE-2026-33680) with a task attachment IDOR (CVE-2026-33678), attackers can read or delete any file attachment on the system.
Vikunja is an open-source, self-hosted task management platform that provides collaboration features, including project sharing and file attachments. The platform exposes a REST API to facilitate client-server communication. Two distinct vulnerabilities, identified as CVE-2026-33680 and CVE-2026-33678, reside within this API infrastructure.
CVE-2026-33680 is an Improper Authorization (CWE-285) vulnerability in the link-sharing mechanism. It permits an actor with read-only access to extract the authentication hashes of higher-privileged link shares. CVE-2026-33678 is an Insecure Direct Object Reference (CWE-639) within the task attachment functionality. It allows authenticated users to access arbitrary attachments across the entire instance.
When chained together, these vulnerabilities yield an advisory categorized under GHSA-2PV8-4C52-MF8J. An attacker possessing a single, low-privileged read-only link share can systematically elevate their privileges and compromise the confidentiality and integrity of all file attachments hosted on the Vikunja instance.
The foundation of the attack relies on architectural inconsistencies within Vikunja's generic Create, Read, Update, Delete (CRUD) handler implementation. The ReadAllWeb handler is responsible for listing collections of objects. This handler neglected to enforce the model-level CanRead() permission check with sufficient granularity for link shares.
In the pkg/models/link_sharing.go module, the ReadAll() method validated access by verifying project.CanRead(s, a). A session established via a link share intrinsically possesses project-level read access, satisfying this preliminary check. Consequently, the API returned the complete list of link shares for the requested project, inadvertently including the secret hash field used as the bearer token for each share.
The second component of the vulnerability chain resides in the task attachment model. The database lookup function for attachments retrieved records based solely on the unique attachment ID. The query execution failed to bind the attachment lookup to the specific task ID provided in the URL path and verified by the authorization layer. This disconnection between the authorized task identifier and the retrieved attachment identifier created the IDOR vulnerability.
The link-share hash disclosure originates in the ReadAll method. Prior to the patch, the system allowed link-share authenticated users to execute the function without explicit restrictions against listing peer shares. The commit 9efe1fadba817923c7c7f5953c3e9e9c5683bbf3 introduced a hard block for link-share users.
// Vulnerable Implementation
func (l *LinkSharing) ReadAll(s *xorm.Session, a web.Auth) (interface{}, error) {
// Missing check for link share auth types
shares := make([]*LinkSharing, 0)
err := s.Where("project_id = ?", l.ProjectID).Find(&shares)
return shares, err
}
// Patched Implementation (Commit 9efe1fadba817923c7c7f5953c3e9e9c5683bbf3)
func (l *LinkSharing) ReadAll(s *xorm.Session, a web.Auth) (interface{}, error) {
if _, is := a.(*LinkSharing); is {
return nil, ErrGenericForbidden{}
}
// ... execution continues to fetch shares for valid users
}Commit 5cd5dc409bfc807f79dac5e4ef4aec54b6efd6e2 further restricted the endpoint by requiring explicit administrator privileges to list project shares. This enforces a principle of least privilege, ensuring standard users cannot enumerate collaboration links.
The attachment IDOR fix required modifying the ReadOne() method to enforce the contextual relationship between the task and the attachment. The patched implementation actively verifies that the TaskID of the retrieved attachment record matches the TaskID specified in the authorized request path, effectively neutralizing the IDOR vector.
The exploitation process requires the attacker to secure initial access via a valid 'Link Share' URL. This URL is often distributed publicly or semi-publicly for collaboration purposes. Upon obtaining this link, the attacker extracts the bearer token and authenticates against the Vikunja API.
The attacker issues a GET request to /api/v1/projects/{id}/shares. The API response contains an array of all active shares for the project. The attacker parses this JSON response to locate a share object possessing 'Admin' or 'Write' privileges and extracts the associated secret hash string.
Using the extracted high-privileged hash, the attacker configures their API client to use the new bearer token. They now have complete administrative control over the targeted project. The attacker selects a valid task ID within this project to satisfy the preliminary TaskAttachment permission check.
The attacker initiates a loop, issuing GET and DELETE requests to /api/v1/tasks/{validTaskId}/attachments/{targetAttachmentId}. They increment the targetAttachmentId integer sequentially. The application validates that the attacker has access to {validTaskId}, but serves the file corresponding to {targetAttachmentId}, allowing the extraction or destruction of all files across the platform.
The chained execution of CVE-2026-33680 and CVE-2026-33678 results in an instance-wide data breach. The primary impact is a severe loss of confidentiality. An attacker can systematically download every file attachment uploaded to the Vikunja server, bypassing all project and user isolation boundaries.
The secondary impact involves a total loss of integrity for the stored attachments. The authorization bypass extends to file deletion mechanisms. An attacker can issue HTTP DELETE requests using the same sequential IDOR technique to permanently remove attachments from the server's storage backend and database.
The vulnerability requires minimal prerequisites. The attacker only needs a single valid link share, which requires no registered user account on the target system. The attack complexity is low, and the process can be fully automated using standard HTTP client libraries, maximizing the potential for rapid data exfiltration before detection.
The vendor addressed both vulnerabilities in a sequence of rapid patches. Version 2.2.1 implemented the initial mitigation by directly blocking link-share authenticated callers from accessing the ReadAll() endpoint for project shares. This version also corrected the database query logic in TaskAttachment.ReadOne() to enforce task-ID binding.
Version 2.2.2 introduced structural security hardening. The backend was updated to strictly require project-level administration rights to list link shares. Additionally, commit 74d1bddb3ab32fc8983d778bb65e89b1d50227d6 implemented client-side visibility controls, completely hiding the sharing section in the user interface for non-administrative accounts.
Administrators must update their Vikunja deployments to version 2.2.2 or later immediately. Organizations unable to patch immediately should disable the link-sharing feature entirely or restrict network access to the API endpoints using a Web Application Firewall. Existing link shares should be audited and revoked if suspicious access patterns are detected in the application logs.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Vikunja Vikunja | < 2.2.1 | 2.2.1 |
Vikunja Vikunja | < 2.2.2 | 2.2.2 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-285, CWE-639 |
| Attack Vector | Network |
| CVSS Score | 8.1 |
| Impact | High Confidentiality, High Integrity |
| Exploit Status | weaponized |
| KEV Status | Not Listed |
Improper Authorization and Insecure Direct Object Reference