Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2025-61152

CVE-2025-61152: python-jose Auth Bypass Vulnerability

CVE-2025-61152 is an authentication bypass flaw in python-jose that allows JWT tokens with 'alg=none' to bypass signature verification, enabling privilege escalation. This article covers technical details, affected versions, and mitigations.

Published:

CVE-2025-61152 Overview

CVE-2025-61152 affects the python-jose library through version 3.3.0. The library accepts JSON Web Tokens (JWTs) with the alg=none header and decodes them without cryptographic signature verification. An attacker can craft a forged token containing arbitrary claims, such as is_admin=true, and submit it to applications that rely on python-jose for token validation. The behavior can lead to authentication bypass and privilege escalation in downstream applications ([CWE-269]).

All parties involved agree the issue is only reachable when developers explicitly configure verify_signature: False, and therefore the report is contested as not being a library defect. The advisory remains published to inform integrators reviewing their JWT validation logic.

Critical Impact

Applications passing verify_signature=False to python-jose may accept alg=none tokens with attacker-controlled claims, enabling unauthorized access or privilege escalation.

Affected Products

  • python-jose versions through 3.3.0
  • Python applications using python-jose for JWT decoding with verify_signature=False
  • Downstream services depending on python-jose for authentication token validation

Discovery Timeline

  • 2025-10-10 - CVE-2025-61152 published to the National Vulnerability Database
  • 2026-06-17 - Last updated in NVD database

Technical Details for CVE-2025-61152

Vulnerability Analysis

JSON Web Tokens carry a header field named alg that specifies the signing algorithm. The none algorithm value indicates an unsigned token and was defined in the original JWT specification. Libraries that honor alg=none without checking application intent risk accepting tokens that were never cryptographically signed.

In python-jose through 3.3.0, the jwt.decode function honors alg=none when the caller disables signature verification with verify_signature=False. The library does not enforce a separate check that rejects unsigned tokens in this state. An attacker who can submit a token to such an endpoint controls every claim in the payload, including identity, roles, and expiration.

The issue is categorized as improper privilege management ([CWE-269]) because forged claims can grant elevated permissions inside applications that trust decoded token contents.

Root Cause

The root cause is a library design choice that treats alg=none as a valid decoding path when the caller opts out of signature verification. The library relies on the developer to reject alg=none explicitly rather than blocking the algorithm by default when verification is disabled. Applications that decode tokens for inspection but then trust the resulting claims for authorization decisions fall directly into the failure mode.

Attack Vector

An attacker constructs a JWT with the header {"alg":"none","typ":"JWT"}, sets the payload to arbitrary claims, and appends an empty signature segment. The attacker submits the token to any endpoint that decodes it using python-jose with verify_signature=False. The application then reads attacker-controlled claims as if they were authenticated. No credentials, user interaction, or prior access are required.

A sanitized description of the exploitation flow appears in the public advisory referenced below. See the GitHub CVE-2025-61152 Advisory for the proof-of-concept details.

Detection Methods for CVE-2025-61152

Indicators of Compromise

  • Inbound JWTs whose header decodes to {"alg":"none"} reaching authentication or authorization endpoints
  • Requests bearing JWTs with an empty third segment following the final . separator
  • Application logs showing successful authentication events that lack a corresponding signature verification log entry
  • Sudden appearance of privileged claims such as is_admin=true or elevated role values from unexpected source addresses

Detection Strategies

  • Grep application source and dependencies for verify_signature=False, options={"verify_signature": False}, and calls to jwt.get_unverified_claims used for authorization
  • Inventory Python projects that pin python-jose<=3.3.0 in requirements.txt, poetry.lock, or Pipfile.lock
  • Add web application firewall or API gateway rules that decode the JWT header and block tokens where alg equals none

Monitoring Recommendations

  • Log the alg value of every JWT accepted by authentication middleware and alert on any non-approved algorithm
  • Correlate authentication events with downstream privilege changes to detect claim tampering
  • Track dependency inventories via software composition analysis (SCA) tools and flag any deployment of python-jose at or below 3.3.0

How to Mitigate CVE-2025-61152

Immediate Actions Required

  • Audit all uses of python-jose and remove any call that passes verify_signature=False when the decoded claims are used for authorization
  • Enforce an allow-list of signing algorithms such as RS256, ES256, or HS256 and reject none explicitly
  • Rotate any JWT signing keys that may have been exposed through logs or code paths that skipped verification
  • Re-issue tokens for active sessions after remediation to invalidate any forged tokens still in circulation

Patch Information

At the time of publication, the maintainers and reporters agree the behavior only surfaces when the caller sets verify_signature: False, and no library patch is listed in NVD. Consult the GitHub Python-Jose Issue #391 and the PyPI Python-Jose Package page for the current maintenance status and any successor libraries recommended by the maintainers.

Workarounds

  • Wrap jwt.decode calls in a helper that rejects tokens whose header contains alg=none before any claim is read
  • Pass an explicit algorithms=["RS256"] (or the algorithm your issuer uses) argument to every jwt.decode call and keep signature verification enabled
  • Where token introspection without verification is genuinely required, isolate that logic and never use the resulting claims for authorization decisions
bash
# Configuration example: reject alg=none before decoding
python - <<'PY'
from jose import jwt

def safe_decode(token, key, algorithms):
    header = jwt.get_unverified_header(token)
    if header.get("alg", "").lower() == "none":
        raise ValueError("Unsigned JWT rejected")
    if header.get("alg") not in algorithms:
        raise ValueError("Disallowed JWT algorithm")
    return jwt.decode(token, key, algorithms=algorithms)
PY

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.