The vulnerability is an authorization bypass in Vikunja's API token handling. The core of the issue lies in the models.CanDoAPIRoute function, which was responsible for checking if an API token had the necessary permissions to access a given API route.
The original implementation of CanDoAPIRoute incorrectly determined permissions. It would parse the request URL to guess the required permission scope, but it failed to consider the HTTP method (e.g., GET, POST, DELETE). This created a "method confusion" vulnerability.
For the specific case of project backgrounds, two routes were defined for the same URL path but with different HTTP methods and permissions:
GET /api/v1/projects/:project/background required projects.background permission.
DELETE /api/v1/projects/:project/background required projects.background_delete permission.
Because of the flaw in CanDoAPIRoute, when a DELETE request was made, the function only checked for a permission matching the path, which it derived as background. A token holding the projects.background permission would therefore be granted access, allowing it to call the handler.RemoveProjectBackground function and delete the project background, even though it lacked the explicit projects.background_delete permission.
The fix in commit 6a0f39b252a81fa4b19dc56dc889183acc9225ae completely rewrites models.CanDoAPIRoute. The new logic iterates through the permissions granted to the token and strictly checks both the HTTP method and the URL path against the details registered for each permission, eliminating the method confusion and ensuring that API tokens can only access the exact routes they are authorized for.
Therefore, the key vulnerable function is models.CanDoAPIRoute, and handler.RemoveProjectBackground is the function that would be observed in a runtime profile during the exploitation of this vulnerability, as it's the endpoint that performs the unauthorized destructive action.