Threats Tagged 'ghsa-vvcv-vpph-h844'
1 threat
Most recently published first
| Severity | CVSS | Signals | Threat | Source | Published | Score and star |
|---|---|---|---|---|---|---|
| High | 8.6 | EPSS 0.5% | CVE-2026-68581vikunja · Incorrect Authorization High8.6EPSS 0.5%CVE Database V5CVE-2026-68581 Executive Summary Vikunja accepts both regular-user JSON Web Tokens (JWTs) and link-share JWTs through its generic authenticated API route group. A link-share JWT resolves to a `models.LinkSharing` principal whose `GetID()` method returns the numeric `link_shares.id`. The API-token management model then treats that generic numeric value as a `users.id` when it creates, lists, and deletes API tokens. Because `users.id` and `link_shares.id` are independent positive sequences, a link share whose ID equals another user's ID is treated as that user by `/api/v1/tokens`. An ordinary authenticated attacker can obtain a target's numeric user ID through authenticated user search and create link shares on an attacker-writable project until the link-share sequence reaches that value. The colliding link-share principal can then list the target's API-token metadata, issue a new API token owned by the target, and delete target-owned API tokens. The newly issued token operates with attacker-selected valid API scopes under the target user's existing permissions. I reviewed the vulnerable `v2.3.0` source, the introducing commit, the stable tag history, and the inspected main revision directly. I also reviewed the recorded local HTTP and native-router validation results. Dynamic testing used only a local `v2.3.0` Docker deployment with PostgreSQL and synthetic data; I did not test any public, hosted, or otherwise external instance. Historical tags were checked from source rather than exercised dynamically. | Field | Value | | --- | --- | | Product | Vikunja API | | Status | Validated; disclosure-ready | | Confirmed affected stable versions | `v0.22.0` through `v2.3.0`, inclusive | | Nearest confirmed unaffected stable version | `v0.21.0` | | Introducing commit | `e6b25bd57b537ef9a72b5acdadf446ca5ef77bfa` | | Latest inspected affected main revision | `95b7e673fb5ee407498fa4b13e8b4c57847a4a0b` | | Fixed version | Unknown; no verified fix commit or release was identified | | Severity | High, CVSS v3.1 score 8.1 | | Vector | `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N` | | Weakness | Primary: CWE-863 (Incorrect Authorization); secondary: CWE-639 | The stable range is source-based. The issue first became reachable when commit `e6b25bd57b...` added the authenticated API-token CRUD routes while retaining the generic `web.Auth.GetID()` ownership model. `v0.21.0` does not contain the API-token model or these routes. All containing stable tags from `v0.22.0` through `v2.3.0` retain the vulnerable source-to-sink tuple. Downstream forks and vendor-specific builds were not assessed. ## Background ### Two authenticated principal types share one numeric interface Vikunja's authenticated route group is protected by a common token middleware. That middleware can establish a regular user, an API-token owner, or a link share as the request's `web.Auth` principal. The `/api/v1/tokens` handlers are registered on this generic group in `pkg/routes/routes.go`: ```go a.Use(SetupTokenMiddleware()) // API Tokens apiTokenProvider := &handler.WebHandler{ EmptyStruct: func() handler.CObject { return &models.APIToken{} }, } a.GET("/tokens", apiTokenProvider.ReadAllWeb) a.PUT("/tokens", apiTokenProvider.CreateWeb) a.DELETE("/tokens/:token", apiTokenProvider.DeleteWeb) ``` The security-sensitive detail is that authentication answers *which object is the principal*, while `web.Auth.GetID()` exposes only an untyped integer. A regular user's ID belongs to the `users` namespace. A link-share ID belongs to the separately allocated `link_shares` namespace. Equality between those integers does not imply that the principals represent the same actor. ### Link-share authentication preserves the share-row ID `pkg/modules/auth/auth.go` creates a link-share JWT with the share's numeric ID and later resolves that token to a `models.LinkSharing` object: ```go claims["type"] = AuthTypeLinkShare claims["id"] = share.ID claims["hash"] = share.Hash claims["project_id"] = share.ProjectID // ... if typ == AuthTypeLinkShare && config.ServiceEnableLinkSharing.GetBool() { s := db.NewSession() defer s.Close() return models.GetLinkShareFromClaims(s, claims) } ``` The `LinkSharing` model declares its own positive auto-incrementing key and returns it unchanged through the generic interface in `pkg/models/link_sharing.go`: ```go type LinkSharing struct { ID int64 `xorm:"bigint autoincr not null unique pk" json:"id" param:"share"` // ... } func (share *LinkSharing) GetID() int64 { return share.ID } ``` Link shares are expected to act within the shared project's permission boundary. API-token management is instead a user-account credential boundary: tokens are owned by users and can authorize future requests as those users. The normal invariant should therefore be that only a positively identified regular-user principal may enter API-token management, and its user ID must be used as the owner key. ### Attacker capabilities The validated attacker is an ord | CVE Database V5 |
Showing 1–1 of 1 result