{"schema":"threatline.record/2","record":{"id":"CVE-2026-62376","aliases":["GHSA-r6w9-259g-gwrv","GO-2026-6748"],"summary":"Vikunja: Plaintext storage of password-reset/email-confirm tokens in database enables account takeover on DB read access","details":"### Summary\n\nVikunja stores password-reset, email-confirmation, and account-deletion tokens in the `user_tokens` table in **plaintext**. If an attacker gains read access to the database through a backup leak, misconfigured storage, or SQL-level exposure, they can immediately use pending tokens to take over user accounts without knowing passwords.\n\n### Details\n\n`pkg/user/token.go` — `genToken()` stores the raw random string directly:\n```go\nfunc genToken(u *User, kind TokenKind) (*Token, error) {\n    tokenStr, err := utils.CryptoRandomString(tokenSize)\n    ...\n    return &Token{\n        UserID: u.ID,\n        Kind:   kind,\n        Token:  tokenStr,  // stored as-is, no hashing\n    }, nil\n}\n```\n\nLookup also uses plaintext equality:\n```go\nfunc getToken(s *xorm.Session, token string, kind TokenKind) (t *Token, err error) {\n    has, err := s.Where(\"kind = ? AND token = ?\", kind, token).Get(t)\n}\n```\n\nAffected token types:\n- `TokenPasswordReset` (`pkg/user/user_password_reset.go:120`)\n- `TokenEmailConfirm` (`pkg/user/user_create.go:101`, `pkg/user/update_email.go:88`)\n- `TokenAccountDeletion` (`pkg/user/delete.go:102`)\n\nNote: CalDAV tokens correctly use `generateHashedToken` with bcrypt — the same protection is absent for the above types.\n\n### PoC\n\n```sql\n-- Attacker with DB read dumps all pending password-reset tokens:\nSELECT u.email, t.token FROM user_tokens t\nJOIN users u ON u.id = t.user_id WHERE t.kind = 1;\n\n-- Then takes over any account:\ncurl -X POST https://vikunja.example.com/api/v1/user/password/reset \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"token\": \"<plaintext_from_db>\", \"new_password\": \"AttackerPass1!\"}'\n```\n\n### Impact\n\nAny read access to the database (leaked backup, cloud misconfiguration, secondary SQLi) allows an attacker to take over every user account with a pending reset token within the 24-hour token lifetime. Full account takeover including admin accounts.\n\n### Fix\n\nReplace `genToken` with `generateHashedToken` for `TokenPasswordReset`, `TokenEmailConfirm`, and `TokenAccountDeletion`. Update the corresponding lookup to use bcrypt comparison (`bcrypt.CompareHashAndPassword`) rather than direct SQL equality, mirroring the existing CalDAV token implementation in the same file.\n\nIf possible, please apply for a CVE number when posting.","categories":["Libraries & packages"],"product":"code.vikunja.io/api","vendor":"go-vikunja","ecosystem":"go","affected_ranges":[{"source":"GitHub Advisory Database","source_url":"https://github.com/advisories/GHSA-r6w9-259g-gwrv","source_modified_at":"2026-10-09T20:49:15Z","fetched_at":"2026-10-23T18:42:43.628194Z","package":{"ecosystem":"go","name":"code.vikunja.io/api"},"range":"<= 2.3.0"},{"source":"CVE List","source_url":"https://www.cve.org/CVERecord?id=CVE-2026-62376","source_modified_at":"2026-10-13T18:31:03.228Z","fetched_at":"2026-10-23T18:45:31.882637Z","product":"vikunja","vendor":"go-vikunja","versions":[{"version":"< 2.4.0","status":"affected"}],"defaultStatus":null},{"source":"OSV","source_url":"https://osv.dev/vulnerability/GHSA-r6w9-259g-gwrv","source_modified_at":"2026-10-19T21:40:52.037882708Z","fetched_at":"2026-10-23T18:45:31.882637Z","package":{"name":"code.vikunja.io/api","ecosystem":"Go","purl":"pkg:golang/code.vikunja.io/api"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"2.4.0"}]}],"versions":[]}],"fixed_versions":[{"source":"GitHub Advisory Database","source_url":"https://github.com/advisories/GHSA-r6w9-259g-gwrv","source_modified_at":"2026-10-09T20:49:15Z","fetched_at":"2026-10-23T18:42:43.628194Z","package":{"ecosystem":"go","name":"code.vikunja.io/api"},"version":"2.4.0"},{"source":"OSV","source_url":"https://osv.dev/vulnerability/GHSA-r6w9-259g-gwrv","source_modified_at":"2026-10-19T21:40:52.037882708Z","fetched_at":"2026-10-23T18:45:31.882637Z","package":{"name":"code.vikunja.io/api","ecosystem":"Go","purl":"pkg:golang/code.vikunja.io/api"},"version":"2.4.0"}],"cvss":8.1,"severity":"High","kev":{"listed":false},"epss":{"probability":0.00215,"percentile":0.11225,"score_date":"2026-10-23"},"published_at":"2026-10-09T20:50:35.524Z","modified_at":"2026-10-19T21:40:52.037882708Z","provenance":[{"source":"GitHub Advisory Database","url":"https://github.com/advisories/GHSA-r6w9-259g-gwrv","fetched_at":"2026-10-23T18:42:43.628194Z","source_modified_at":"2026-10-09T20:49:15Z"},{"source":"CVE List","url":"https://www.cve.org/CVERecord?id=CVE-2026-62376","fetched_at":"2026-10-23T18:45:31.882637Z","source_modified_at":"2026-10-13T18:31:03.228Z"},{"source":"OSV","url":"https://osv.dev/vulnerability/GHSA-r6w9-259g-gwrv","fetched_at":"2026-10-23T18:45:31.882637Z","source_modified_at":"2026-10-19T21:40:52.037882708Z"},{"source":"EPSS","url":"https://api.first.org/data/v1/epss?cve=CVE-2026-62376","fetched_at":"2026-10-23T18:42:43.628194Z","source_modified_at":"2026-10-23"}],"sources":["GitHub Advisory Database","CVE List","OSV","EPSS"],"references":[{"source":"CVE List","url":"https://github.com/go-vikunja/vikunja/security/advisories/GHSA-r6w9-259g-gwrv","tags":["exploit"]},{"source":"CVE List","url":"https://github.com/go-vikunja/vikunja/commit/00fd2c6155c01faae99be4226b931d8091fd6323","tags":["x_refsource_MISC"]},{"source":"CVE List","url":"https://github.com/go-vikunja/vikunja/commit/3a0ea15d8c18ff960bc98ae39950fa7a14b0af7d","tags":["x_refsource_MISC"]},{"source":"CVE List","url":"https://github.com/go-vikunja/vikunja/commit/e31ea2de5040fa63bc97cf4df63bafed3bd9ad85","tags":["x_refsource_MISC"]},{"source":"CVE List","url":"https://github.com/go-vikunja/vikunja/releases/tag/v2.4.0","tags":["x_refsource_MISC"]},{"url":"https://github.com/advisories/GHSA-r6w9-259g-gwrv","source":"GitHub Advisory Database"}],"locations":[],"motoko_assessment":{"status":"requires_architecture_review","automatic_remediation":false},"cve_state":"PUBLISHED","ssvc":{"exploitation":"poc","automatable":"no","technical_impact":"total","assessed_at":"2026-10-13T18:30:25.138466Z"},"classification":{"method":"product-first software-layer rules","rules_version":"2.1","matched_on":"ecosystem","confidence":"heuristic","reviewed":false},"change_timestamp":"2026-10-19T21:40:52.037882708Z","content_hash":"0ea02d65a6671f3195c90c378c032e94fdb2e0b7ecad44ab7922c88ece817478"}}
