Skip to main content

Python CVE-2026-35597

| EUVDEUVD-2026-21422 HIGH
Improper Restriction of Excessive Authentication Attempts (CWE-307)
2026-04-10 https://github.com/go-vikunja/vikunja GHSA-fgfv-pv97-6cmj
7.5
CVSS 3.1 · NVD
View

Vulnerability Assessment

Weakness
CWE
OWASP Top 10:2025
A07:2025 - Authentication Failures
ASVS 5.0
V6 - Authentication Brute-force prevention, rate limiting
Impact

CVSS 5.9 with AV:N/AC:H/PR:N indicates network-accessible unauthenticated attack with high complexity, conferring confidentiality impact without integrity or availability loss. The high attack complexity reflects the need for an attacker to obtain the target user's password separately (via phishing, credential stuffing, or breach), then brute-force the TOTP code. EPSS probability and active exploitation status are not provided, but the proof-of-concept demonstrates trivial reproducibility on Vikunja v2.2.2. The per-IP rate limit of 10 requests per minute is not a sufficient control against distributed attackers; modern cloud infrastructure enables parallel attempts from hundreds of IPs. Critically, the TOTP code space is only 1 million (6-digit decimal), and with parallelization an attacker could exhaust this within hours. This is a high real-world priority despite the moderate CVSS score because: (1) the precondition (password theft) is common in breach scenarios, (2) the exploit is trivial and no special tools are needed, (3) rate limiting is bypassable, and (4) 2FA defeat completely undermines that security layer. Organizations with TOTP-protected accounts on vulnerable Vikunja versions face direct account compromise risk.

Exploit ScenarioDerived

An attacker obtains a Vikunja user's password via phishing or a credential database breach. The attacker then initiates login with the valid username and password but submits invalid TOTP passcodes (e.g., 000000) in rapid succession. The rate limit of 10 failed attempts per minute per IP is easily circumvented by using a botnet or cloud services with multiple IP ranges. Each failed attempt increments the in-memory counter and triggers account lockout logic, but the StatusAccountLocked database write is rolled back by the login handler. After approximately 100,000 requests (1 million possible 6-digit codes divided by distributed parallelization), the attacker will eventually submit a code that matches the current TOTP value (or cycles through all possibilities), gain access, and compromise the account. A proof-of-concept Python script demonstrating this attack is provided in the CVE description, confirming successful login with valid TOTP after 12+ failed attempts on v2.2.2.

This Week Schedule remediation this week. Why: HIGH severity (CVSS 7.0-8.9).
Patch available 0.0% exploitation probability (EPSS)

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv1 – Apr 10, 2026

Vikunja API brute-forces TOTP codes by exploiting a database transaction rollback bug that prevents account lockout persistence. When TOTP validation fails, the login handler rolls back the database session containing the failed-attempt counter increment and account lock status, leaving the lockout mechanism non-functional while per-IP rate limiting can be bypassed via distributed attack. Unauthenticated remote attackers who possess a user's password can exhaust the 6-digit TOTP code space (only 1 million combinations) and gain unauthorized access. Patch is available as of Vikunja v2.3.0.

RemediationAI

Vendor-released patch: Vikunja v2.3.0 and later. The fix, implemented in commit 6ca0151d02fa0e8c7e2181ab916a28e08caaaec8 and merged via PR #2576, modifies HandleFailedTOTPAuth to create and commit its own independent database session for the account lockout operation, ensuring the StatusAccountLocked write persists regardless of the caller's transaction rollback. Immediate action: upgrade all Vikunja instances to v2.3.0 or later. If immediate patching is not feasible, consider temporarily disabling TOTP enforcement or implementing additional per-user IP allowlist controls and monitoring failed TOTP attempts in application logs to detect brute-force activity. Detailed patching guidance is available at https://github.com/go-vikunja/vikunja/security/advisories/GHSA-fgfv-pv97-6cmj.

Affected VersionsENISA

vikunja < 2.3.0

Affected Packages

go code.vikunja.io/api fix: 2.3.0
euvd vikunja fix: 2.3.0

Source: OSV (Open Source Vulnerabilities)

Affects your stack

Affects 2 packages in go, euvd

Checking this CVE against your own stacks and servers is part of the Basic plan and up.

Technical ContextAI · show details

Vikunja is a Go-based API application for task/project management that implements TOTP two-factor authentication. The vulnerability resides in the interaction between the login handler (pkg/routes/api/v1/login.go) and the TOTP authentication module (pkg/user/totp.go). When a TOTP passcode validation fails, the login handler invokes HandleFailedTOTPAuth to increment an in-memory failed-attempt counter and, after 10 attempts, write a StatusAccountLocked flag to the user record via database session s. However, the login handler unconditionally calls s.Rollback() on all error paths, which reverses the database write of the account lock status. The in-memory counter increments correctly and subsequent calls execute the lockout code, but the database mutation is discarded on each failure. This is a CWE-307 (Improper Restriction of Rendered UI Layers or Frames) related to authentication bypass through insufficient lockout enforcement. The per-IP rate limit of 10 requests per minute provides some friction but is bypassable via distributed source IPs. The CPE is pkg:go/code.vikunja.io_api.

Know when Python gets its next vulnerability

  • Watch products and get an email when something new is published
  • Check this CVE against your own stack and servers
  • Exploit and PoC references, threat intelligence from 22 sources

No credit card · 7-day full trial

Severity by source

NVD PRIMARY 7.5 HIGH
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
SUSE HIGH

Primary rating from NVD.

CVSS VectorNVD

Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
None
Availability
None

Lifecycle Timeline

4
Severity Changed
Oct 26, 2026 - 22:24 NVD
MEDIUM HIGH
CVSS changed
Oct 26, 2026 - 22:24 NVD
5.9 (MEDIUM) 7.5 (HIGH)
Patch released
Apr 10, 2026 - 16:00 nvd
Patch available
CVE Published
Apr 10, 2026 - 15:34 nvd
MEDIUM 5.9

DescriptionNVD

Summary

The TOTP failed-attempt lockout mechanism is non-functional due to a database transaction handling bug. The account lock is written to the same database session that the login handler always rolls back on TOTP failure, so the lockout is triggered but never persisted. This allows unlimited brute-force attempts against TOTP codes.

Details

When a TOTP validation fails, the login handler at pkg/routes/api/v1/login.go:95-101 calls HandleFailedTOTPAuth and then unconditionally rolls back:

go
if err != nil {
    if user2.IsErrInvalidTOTPPasscode(err) {
        user2.HandleFailedTOTPAuth(s, user)
    }
    _ = s.Rollback()
    return err
}

HandleFailedTOTPAuth at pkg/user/totp.go:201-247 uses an in-memory counter (key-value store) to track failed attempts. When the counter reaches 10, it calls user.SetStatus(s, StatusAccountLocked) on the same database session s. Because the login handler always rolls back after a TOTP failure, the StatusAccountLocked write is undone.

The in-memory counter correctly increments past 10, so the lockout code executes on every subsequent attempt, but the database write is rolled back every time.

Proof of Concept

Tested on Vikunja v2.2.2. Requires pyotp (pip install pyotp).

python
import requests, time, pyotp

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

def h(token):
    return {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
# setup: login, enroll and enable TOTP
token = requests.post(f"{API}/login",
    json={"username": "totp_user", "password": "TotpUser1!"}).json()["token"]
secret = requests.post(f"{API}/user/settings/totp/enroll", headers=h(token)).json()["secret"]
totp = pyotp.TOTP(secret)
requests.post(f"{API}/user/settings/totp/enable", headers=h(token),
              json={"passcode": totp.now()})
# send 9 failed attempts (rate limit is 10/min)
for i in range(1, 10):
    r = requests.post(f"{API}/login",
        json={"username": "totp_user", "password": "TotpUser1!", "totp_passcode": "000000"})
    print(f"Attempt {i}: {r.status_code} code={r.json().get('code')}")
# wait for rate limit reset, send 3 more (past the 10-attempt lockout threshold)
time.sleep(65)
for i in range(10, 13):
    r = requests.post(f"{API}/login",
        json={"username": "totp_user", "password": "TotpUser1!", "totp_passcode": "000000"})
    print(f"Attempt {i}: {r.status_code} code={r.json().get('code')}")
# wait for rate limit, try with valid TOTP
time.sleep(65)
r = requests.post(f"{API}/login",
    json={"username": "totp_user", "password": "TotpUser1!", "totp_passcode": totp.now()})
print(f"Valid TOTP login: {r.status_code}")
# 200 - account was never locked

Output:

Attempt 1: 412 code=1017
...
Attempt 9: 412 code=1017
Attempt 10: 412 code=1017
Attempt 11: 412 code=1017
Attempt 12: 412 code=1017
Valid TOTP login: 200

The account was never locked despite exceeding the 10-attempt threshold. The per-IP rate limit of 10 requests/minute requires spacing attempts, but an attacker with multiple source IPs can parallelize.

Impact

An attacker who has obtained a user's password (via phishing, credential stuffing, or database breach) can bypass TOTP two-factor authentication by brute-forcing 6-digit codes. The intended account lockout after 10 failed attempts never takes effect. While per-IP rate limiting provides friction, a distributed attacker can exhaust the TOTP code space.

Recommended Fix

Have HandleFailedTOTPAuth create and commit its own independent database session for the lockout operation:

go
// Use a new session so the lockout persists regardless of caller's rollback
lockoutSession := db.NewSession()
defer lockoutSession.Close()
err = user.SetStatus(lockoutSession, StatusAccountLocked)
if err != nil {
    _ = lockoutSession.Rollback()
    return
}
_ = lockoutSession.Commit()

--- *Found and reported by aisafe.io*

Threat Intelligence Overview

EPSS Score
0.0%
Top 91% exploitable
Threat Intel
1
1 source
Data Quality
7 sources
Confidence: High
EUVD NVD CVE.org EPSS Vulnrichment GHSA Vendor GitHub

How this decision was reached

The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.

SignalValue
Severity HIGH
CISA KEV No
Public POC No
EPSS 0.0%
Patch available Yes
Active threat No
Deciding rule
HIGH severity (CVSS 7.0-8.9)
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision· derived
Scheduled
Exploitation
Poc
System Exposure· derived
Open
Automatable
No
Human Impact· derived
Medium
Technical Impact
Partial

Priority Score

38
Low Medium High Critical
KEV: 0
EPSS: 0
CVSS: +38
PoC: 0
Weaponized: 0
Threat intel: 0
Gov advisory: 0

Attack Technique

Authentication bypass attacks exploit flaws in the verification mechanisms that control access to systems and applications.

More in Python

View all
CVE-2025-24016 CRITICAL POC
9.9 Feb 10

Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t

CVE-2025-27520 CRITICAL POC
9.8 Apr 04

BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser

CVE-2025-2945 CRITICAL POC
9.9 Apr 03

pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi

CVE-2013-5093 MEDIUM POC
6.8 Sep 27

The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python

CVE-2025-32375 CRITICAL POC
9.8 Apr 09

BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica

CVE-2014-0224 HIGH POC
7.4 Jun 05

OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph

CVE-2024-21644 HIGH POC
7.5 Jan 08

pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.

CVE-2026-33017 CRITICAL POC
9.3 Mar 17

Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301

CVE-2017-9462 HIGH POC
8.8 Jun 06

In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse

CVE-2026-49869 CRITICAL POC
10.0 Jun 26

Unauthenticated remote code execution affects Kestra OSS (the open-source event-driven orchestration platform) prior to

CVE-2026-39987 CRITICAL POC
9.3 Apr 08

Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/

CVE-2024-21645 MEDIUM POC
5.3 Jan 08

pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne

Vendor StatusVendor

SUSE

Severity: Important
Product Status
SUSE Linux Enterprise Server 16.1 Affected
SUSE Linux Enterprise Server for SAP applications 16.1 Affected
SUSE Linux Enterprise Module for Package Hub 15 SP5 Affected
SUSE Linux Enterprise Module for Package Hub 15 SP6 Affected
openSUSE Leap 15.5 Affected

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy