GHSA-xv7q-fvmc-jx96: Go/code.vikunja.io/api vulnerability

Published Oct 9, 2026
·
Updated

Summary

With the per-provider OIDC emailfallback option enabled, Vikunja links an SSO login to a pre-existing local (username+password) account using only the email claim — no emailverified (or Microsoft xmsedov) check and no password check, on the unauthenticated callback. An attacker who can make the configured issuer emit a token bearing a victim's email logs in as that victim with a full session and no victim interaction (the nOAuth / Grafana CVE-2023-3128 class). The 2.3.0 fix for GHSA-8jvc-mcx6-r4cg added a TOTP gate, not an emailverified gate, so users without TOTP remain exposed.

Details

References are pkg/modules/auth/openid/openid.go at HEAD. Identity is first resolved on the immutable (issuer, subject) pair (openid.go:428). On a subject miss with emailfallback on, fallbackSearchUsers adds an email-only lookup against local accounts:

go // openid.go:413 searches = append(searches, &user.User{Issuer: user.IssuerLocal, Email: cl.Email})

getUser resolves this via s.Get(), which ANDs non-zero fields -> WHERE issuer='local' AND email=?. Local users always have Issuer="local" (usercreate.go:38), so the lookup matches any local account by email alone; getOrCreateUser returns it and the caller mints a session — the password is never read. The claims struct has no emailverified field (openid.go:80) and getClaims never consults one; a repo-wide grep for emailverified/xmsedov returns nothing. The code already warns about this at openid.go:388 ("Discouraged for untrusted providers where someone can set email without verification") — but enforces nothing.

Impact

Unauthenticated takeover of any existing local account (read/write/delete its projects, tasks, attachments, shares), bypassing the password. Scope notes: only issuer='local' accounts are matched (not pure-SSO users); the attacker's sub is not bound to the victim record, but the attack is repeatable; TOTP users are protected by the 2.3.0 enforceTOTPIfRequired gate (openid.go:250), non-TOTP users are not.

Preconditions

1. Admin enabled emailfallback: true (defaults false — a default install is unaffected). 2. The configured issuer lets the attacker assert the victim's unverified email: a self-service IdP (Keycloak/Authentik/Auth0/Dex with editable email), a mixed federation, or a multi-tenant Entra /common app. iss/aud are pinned, but the attacker controls email, not the issuer. 3. The victim has a local account.

Not reachable against a single-tenant IdP that verifies email and disallows self-set addresses.

Recommended Fix

Add emailverified to the claims struct and require it true on the email-fallback branch before linking to a local account; reject when absent/false. For Entra also require xmsedov and pin multi-tenant configs to an allowed-tenant list. Fail closed on an email collision not backed by a verified email from a trusted single-tenant issuer rather than silently logging the caller in.

Affected Software

1 affected componentFixes available
go/code.vikunja.io/api>=1.0.0<=2.3.0
2.4.0

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade go/code.vikunja.io/api to a version that resolves this vulnerability.

    Fixed in 2.4.0
  2. Configuration

    Disable emailfallback unless it is required; it defaults to false.

    Vikunja per-provider OIDC emailfallback = false
  3. Configuration

    For multi-tenant Entra configurations, pin the issuer to an allowed-tenant list and require the xms_edov claim.

    Microsoft Entra OIDC allowed tenant list = configured allowed tenants
  4. Compensating control

    On the email-fallback branch, require the email_verified claim to be present and true before linking to a local account; reject absent or false values and fail closed on email collisions not backed by a verified email from a trusted single-tenant issuer.

Event History

Oct 9, 2026
Advisory Published
via GitHub·08:49 PM
Data Sourced
via GitHub·08:49 PM
DescriptionWeaknessAffected Software

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203