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.
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.
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.
owner, create project P_near with task near and project P_far with task far.P_near with attacker at write permission (permission: 1). Do not share P_far.owner: PUT /api/v1/tasks/{near}/relations with {"other_task_id": far, "relation_kind": "related"} -> 200.attacker: GET /api/v1/tasks/{far} -> 403 (confirms no access).attacker: PUT /api/v1/tasks/{near}/relations with the same body -> 403 (create path is enforced).attacker: DELETE /api/v1/tasks/{near}/relations/related/{far} -> 200 "Successfully deleted."owner: GET /api/v1/tasks/{far} -> related_tasks is now empty.Reproduced against vikunja/vikunja:2.5.0.
Make CanDelete mirror CanCreate: after checking CanUpdate on the base task, also require CanRead on OtherTaskID.
{
"cwe_ids": [
"CWE-285",
"CWE-862"
],
"github_reviewed": true,
"github_reviewed_at": "2026-10-09T20:54:52Z",
"nvd_published_at": null,
"severity": "LOW"
}