Vulnerability GHSA-w2ch-4xgr-22ww

Low Risk
LOW RISK
CVSS Score: 3.0
Score Range: < 4.0
Low severity vulnerabilities (CVSS < 4.0). Hygiene issues that can accumulate but pose lower immediate risk.
3 hours ago
October 09, 2026 at 08:54 PM UTC
Vikunja: Task relation deletion does not check read access to the other task, allowing cross-project relation removal

Summary

Vikunja: Task relation deletion does not check read access to the other task, allowing cross-project relation removal

Details

Summary

Deleting a task relation only requires write access on the base task. Unlike relation creation, it does not verify that the caller can read the other task. A user with write access to one project can therefore delete relations whose other end lives in a project they have no access to. Since the delete removes both the forward and inverse rows, the relation also disappears for the other project's members.

Details

TaskRelation.CanCreate (pkg/models/task_relation_permissions.go:32-52) requires write access on TaskID and read access on OtherTaskID.

TaskRelation.CanDelete (pkg/models/task_relation_permissions.go:25-29) only checks Task{ID: rel.TaskID}.CanUpdate(s, a); OtherTaskID is never authorized.

TaskRelation.Delete (pkg/models/task_relation.go:314-354) then deletes both the (task_id, other_task_id, kind) row and its inverse, so the relation is removed from the far task as well.

Affects DELETE /api/v1/tasks/{id}/relations/{kind}/{otherTaskId} and the equivalent v2 endpoint.

Impact

Low, integrity only. An authenticated user holding write permission on a shared project can remove task relations that link into projects they cannot read. No data is disclosed and no privilege is gained; the attacker cannot recreate the relation. The far project's owner sees the relation vanish without indication of who removed it.

Preconditions: the attacker has write access to a project containing a task that is already related to a task in a project they cannot access.

Proof of Concept

  1. As owner, create project P_near with task near and project P_far with task far.
  2. Share P_near with attacker at write permission (permission: 1). Do not share P_far.
  3. As owner: PUT /api/v1/tasks/{near}/relations with {"other_task_id": far, "relation_kind": "related"} -> 200.
  4. As attacker: GET /api/v1/tasks/{far} -> 403 (confirms no access).
  5. As attacker: PUT /api/v1/tasks/{near}/relations with the same body -> 403 (create path is enforced).
  6. As attacker: DELETE /api/v1/tasks/{near}/relations/related/{far} -> 200 "Successfully deleted."
  7. As owner: GET /api/v1/tasks/{far} -> related_tasks is now empty.

Reproduced against vikunja/vikunja:2.5.0.

Recommended Fix

Make CanDelete mirror CanCreate: after checking CanUpdate on the base task, also require CanRead on OtherTaskID.

Impacted packages

Timeline

Published
3 hours ago
October 09, 2026 at 08:54 PM UTC
Last Modified
3 hours ago
October 09, 2026 at 09:00 PM UTC