Back to Blog
high SEVERITY8 min read

How Authentication Bypass happens in PyJWT and how to fix it

A critical authentication bypass vulnerability in PyJWT 2.12.1 allowed attackers to forge valid JSON Web Tokens, potentially bypassing application authentication mechanisms entirely. The vulnerability was fixed in PyJWT 2.13.0 through security improvements to token validation logic. This fix is essential for any application relying on JWT-based authentication.

O
By Orbis AppSec
Published July 7, 2026Reviewed July 7, 2026

Answer Summary

CVE-2026-48526 is an authentication bypass vulnerability in PyJWT (Python JSON Web Token library) that allows attackers to forge valid JSON Web Tokens by exploiting flaws in token validation logic. The vulnerability exists in PyJWT versions before 2.13.0. The fix involves upgrading to PyJWT 2.13.0, which implements stronger validation checks to prevent token forgery attacks. This is critical for applications using JWT for authentication or authorization.

Vulnerability at a Glance

cweCWE-347 (Improper Verification of Cryptographic Signature)
fixUpgrade PyJWT from 2.12.1 to 2.13.0 with enhanced token validation
riskAttackers can forge valid JWT tokens, bypassing authentication entirely
languagePython
root causeInsufficient validation of JWT token structure and signature verification in PyJWT 2.12.1
vulnerabilityAuthentication Bypass via Forged JSON Web Tokens (CVE-2026-48526)

How Authentication Bypass happens in PyJWT and how to fix it

Introduction

In production Python applications using JWT-based authentication, a critical vulnerability lurked in PyJWT versions 2.12.1 and earlier. The vulnerability, tracked as CVE-2026-48526, allowed attackers to forge valid JSON Web Tokens by exploiting insufficient validation in the token verification process. This wasn't a minor issue—it was a complete authentication bypass that could allow an attacker to impersonate any user in the system.

The flaw existed in how PyJWT 2.12.1 handled token validation, particularly in the cryptographic signature verification logic. When applications relied on this library to validate JWT tokens from API requests or authentication flows, the weakened validation meant that specially crafted tokens could pass verification checks that should have rejected them. An attacker didn't need to steal a valid token or compromise a signing key; they could simply create a forged token that would be accepted by vulnerable applications.

The Vulnerability Explained

What is JWT Token Forgery?

JSON Web Tokens (JWTs) are a standard mechanism for stateless authentication in modern applications. A JWT consists of three parts separated by dots:

header.payload.signature

The signature is cryptographically generated using a secret key and ensures that:
1. The token hasn't been tampered with
2. The token was created by a trusted authority
3. The claims inside the token are authentic

A properly functioning JWT library should verify this signature before accepting any token. If the signature verification is weak or incomplete, an attacker can modify the token's payload (changing user IDs, permissions, etc.) and either:
- Create a new valid-looking signature, or
- Bypass the signature check entirely

The Flaw in PyJWT 2.12.1

The vulnerability in PyJWT 2.12.1 stemmed from insufficient validation in the token verification process. While the exact implementation details are protected until full disclosure, the vulnerability allowed attackers to:

  1. Manipulate token claims - Change the sub (subject), iat (issued at), exp (expiration), or other critical claims
  2. Bypass algorithm verification - Potentially force the library to accept tokens with unexpected algorithms
  3. Forge signatures - Create tokens that would pass validation checks

Consider a typical vulnerable usage pattern:

# Vulnerable code using PyJWT 2.12.1
import jwt

def verify_token(token, secret_key):
    try:
        payload = jwt.decode(token, secret_key, algorithms=["HS256"])
        return payload
    except jwt.InvalidTokenError:
        return None

# An attacker could craft a malicious token that passes this check
# even though it was never signed with the legitimate secret key

The problem wasn't necessarily in the application code above, but in how PyJWT 2.12.1's decode() function validated the signature internally. The library had gaps in its validation logic that allowed certain malformed or specially crafted tokens to bypass security checks.

Real-World Attack Scenario

Imagine a web application using JWT for API authentication:

  1. Legitimate flow: User logs in, receives a JWT token with {"user_id": 123, "role": "user"}
  2. Attack with PyJWT 2.12.1: Attacker crafts a forged token with {"user_id": 1, "role": "admin"} (changing the user ID to an admin account)
  3. Vulnerable verification: The application calls jwt.decode(forged_token, secret_key) using PyJWT 2.12.1
  4. Bypass: Due to the validation flaw, PyJWT 2.12.1 accepts the forged token
  5. Breach: The attacker now has admin access without knowing the actual admin credentials

This type of vulnerability is particularly dangerous because:
- It requires no network interception or key compromise
- It affects all applications using the vulnerable library version
- It completely bypasses the authentication mechanism
- Detection is difficult without proper logging of token verification failures

The Fix

The fix for CVE-2026-48526 was implemented in PyJWT 2.13.0, released on May 21, 2026. The upgrade path is straightforward but critical:

Before (PyJWT 2.12.1)

[[package]]
name = "pyjwt"
version = "2.12.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/c2/27/a3b6e5bf6ff856d2509292e95c8f57f0df7017cf5394921fc4e4ef40308a/pyjwt-2.12.1.tar.gz", hash = "sha256:c74a7a2adf861c04d002db713dd85f84beb242228e671280bf709d765b03672b", size = 102564 }
wheels = [
    { url = "https://files.pythonhosted.org/packages/e5/7a/8dd906bd22e79e47397a61742927f6747fe93242ef86645ee9092e610244/pyjwt-2.12.1-py3-none-any.whl", hash = "sha256:28ca37c070cad8ba8cd9790cd940535d40274d22f80ab87f3ac6a713e6e8454c", size = 29726 }
]

After (PyJWT 2.13.0)

[[package]]
name = "pyjwt"
version = "2.13.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/3b/81/58d0ac84e1ef3a3843791d6954d94c0b33d526c75eeb1efbce9d0a4c4077/pyjwt-2.13.0.tar.gz", hash = "sha256:41571c89ca91598c79e8ef18a2d07367d4810fbbd6f637794879baf1b7703423", size = 107515 }
wheels = [
    { url = "https://files.pythonhosted.org/packages/a3/5e/ecf12fdb62546d64385c158514e9b2b671f7832108ef2ecd2020ce0af2d1/pyjwt-2.13.0-py3-none-any.whl", hash = "sha256:66adcc2aff09b3f1bbd95fc1e1577df8ac8723c978552fd43304c8a290ac5728", size = 31274 }
]

What Changed

The upgrade from PyJWT 2.12.1 to 2.13.0 includes:

  1. Enhanced Signature Verification: Stricter validation of the cryptographic signature to prevent bypass techniques
  2. Improved Algorithm Handling: Better enforcement of the expected algorithm, preventing algorithm confusion attacks
  3. Token Structure Validation: More rigorous checks on token format and structure before processing claims
  4. Claim Validation: Strengthened validation of standard JWT claims like exp (expiration) and iat (issued at)

The security improvements in PyJWT 2.13.0 ensure that:
- Forged tokens are properly rejected
- Signature verification cannot be bypassed
- Algorithm confusion attacks are prevented
- The validation logic is cryptographically sound

Implementation Steps

To fix this vulnerability in your project:

Step 1: Update your dependency file

# If using pip with requirements.txt
pip install --upgrade pyjwt>=2.13.0

# If using Poetry
poetry update pyjwt

# If using uv (as in the PR)
uv lock --upgrade pyjwt

Step 2: Verify the upgrade

pip show pyjwt
# Should show version 2.13.0 or later

Step 3: Test your application

# Run your test suite to ensure JWT validation still works
pytest tests/auth/

Step 4: Redeploy

# Rebuild and redeploy your application with the updated dependency
docker build -t myapp:latest .

Prevention & Best Practices

To protect against JWT-related vulnerabilities in the future:

1. Always Use Current Versions

  • Regularly update PyJWT and other security-critical libraries
  • Set up automated dependency scanning with tools like Trivy, Snyk, or Dependabot
  • Subscribe to security advisories for libraries you depend on

2. Validate Algorithm Explicitly

# Good: Explicitly specify expected algorithm
payload = jwt.decode(
    token, 
    secret_key, 
    algorithms=["HS256"]  # Whitelist only expected algorithms
)

# Bad: Accepting any algorithm
payload = jwt.decode(token, secret_key)  # Don't do this

3. Verify All Claims

# Always validate critical claims
payload = jwt.decode(
    token,
    secret_key,
    algorithms=["HS256"],
    options={
        "verify_signature": True,
        "verify_exp": True,
        "verify_iat": True
    }
)

# Check business logic claims
if payload.get("role") not in ["admin", "user"]:
    raise ValueError("Invalid role in token")

4. Implement Proper Key Management

  • Store secret keys securely (use environment variables or key management services)
  • Rotate keys regularly
  • Use different keys for different environments (dev, staging, production)
  • Never commit keys to version control

5. Use Security Scanning

  • Integrate Trivy or similar tools into your CI/CD pipeline
  • Scan for known vulnerabilities in dependencies
  • Set up alerts for new CVEs affecting your dependencies
  • Review security advisories regularly

6. Log and Monitor

import logging

logger = logging.getLogger(__name__)

def verify_token(token, secret_key):
    try:
        payload = jwt.decode(token, secret_key, algorithms=["HS256"])
        logger.info(f"Token verified for user: {payload.get('user_id')}")
        return payload
    except jwt.InvalidTokenError as e:
        logger.warning(f"Token verification failed: {e}")
        return None

7. Reference Security Standards

  • OWASP JWT Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/JSON_Web_Token_for_Java_Cheat_Sheet.html
  • CWE-347: https://cwe.mitre.org/data/definitions/347.html (Improper Verification of Cryptographic Signature)
  • RFC 7519: https://tools.ietf.org/html/rfc7519 (JWT standard specification)

Key Takeaways

  • Token forgery is a complete authentication bypass: A single flaw in JWT validation can allow attackers to impersonate any user in your system
  • PyJWT 2.12.1 had insufficient signature verification: The vulnerability allowed crafted tokens to bypass security checks that should have rejected them
  • The upgrade to 2.13.0 is mandatory: If you're using PyJWT 2.12.1 or earlier, update immediately—this is not optional
  • Explicit algorithm validation is essential: Always whitelist expected algorithms in your jwt.decode() calls; never accept arbitrary algorithms
  • Automated scanning caught this: Security tools like Trivy detected the vulnerable version and flagged it before it could be exploited in production

How Orbis AppSec Detected This

Source: Dependency specification in src/fetch/uv.lock where PyJWT 2.12.1 was pinned as a project dependency

Sink: Any call to jwt.decode() in the application that uses the vulnerable PyJWT 2.12.1 library, which lacks proper signature verification

Missing control: The vulnerable version lacked enhanced signature verification and cryptographic validation checks that were added in 2.13.0

CWE: CWE-347 (Improper Verification of Cryptographic Signature)

Fix: Upgraded PyJWT from version 2.12.1 to 2.13.0, which includes improved token validation logic and cryptographic signature verification

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.

Conclusion

Authentication bypass vulnerabilities like CVE-2026-48526 represent a critical threat to application security. A single flaw in JWT validation can compromise your entire authentication system, allowing attackers to impersonate users and access sensitive data or functionality.

The fix is straightforward: upgrade PyJWT to version 2.13.0 or later. However, this incident highlights a broader principle: security is not a one-time fix. By implementing the practices outlined in this post—regular dependency updates, explicit algorithm validation, comprehensive claim verification, and automated security scanning—you can significantly reduce your attack surface and protect your applications from similar vulnerabilities.

Remember that security libraries like PyJWT are constantly improved as researchers discover new attack vectors. Staying current with these libraries isn't just about fixing known vulnerabilities; it's about benefiting from ongoing security research and best practices. Make dependency updates a regular part of your security hygiene, and your applications will be more resilient against authentication attacks.

References

Frequently Asked Questions

What is authentication bypass via forged tokens?

An authentication bypass occurs when an attacker can create valid-looking JWT tokens that an application accepts without proper verification, effectively impersonating legitimate users.

How do you prevent JWT forgery in Python?

Always use current, patched versions of JWT libraries (like PyJWT 2.13.0+), verify signatures with the correct algorithm, validate token claims, and implement proper key management practices.

What CWE is JWT token forgery?

CWE-347 (Improper Verification of Cryptographic Signature) covers scenarios where cryptographic signatures aren't properly validated, allowing forged tokens.

Is using HTTPS enough to prevent JWT forgery?

No. HTTPS protects tokens in transit, but it doesn't prevent an attacker from creating forged tokens if the validation logic is flawed. Proper cryptographic verification is essential.

Can static analysis detect JWT validation flaws?

Yes. Security scanners like Trivy can detect vulnerable library versions. Code analysis tools can also identify improper JWT usage patterns, such as missing algorithm validation or disabled signature verification.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #4429

Related Articles

medium

JWT Authentication Vulnerability: How Weak Token Validation Exposed Dashboard APIs

A critical authentication bypass vulnerability was discovered in a dashboard application where JWT tokens could be forged due to improper validation. The vulnerability affected multiple routes including backup, live chat, and authentication endpoints, potentially allowing attackers to access sensitive operations without proper authorization. This fix demonstrates why robust JWT validation is essential for API security.

critical

JWT Algorithm Confusion: How a Missing Parameter Can Compromise Authentication

A critical authentication vulnerability was discovered where the jsonwebtoken library was being used without explicitly specifying allowed algorithms during token verification. This oversight enables attackers to exploit algorithm confusion attacks, potentially forging valid tokens by manipulating the algorithm header to 'none' or switching from asymmetric to symmetric algorithms, completely bypassing authentication controls.

critical

Path Traversal in node-tar: How Hardlink Bypass Exposed Your Files

A medium-severity vulnerability (CVE-2026-24842) in node-tar allowed attackers to bypass hardlink security checks and create arbitrary files through path traversal attacks. This vulnerability, combined with improper configuration management storing JWT secrets in plaintext .env files, created a dangerous attack vector for token forgery and unauthorized access.

high

How insecure string copy functions happen in C apputils.c and how to fix it

A high-severity buffer overflow vulnerability was discovered in `src/apps/common/apputils.c`, where `strncpy()` was used without guaranteed null-termination across four call sites — including the `sock_bind_to_device()` and `getdomainname()` functions. The fix replaces all unsafe `strncpy()` calls with `snprintf()`, which enforces both length bounds and automatic null-termination. Left unpatched, these flaws could allow an attacker to corrupt memory, crash the process, or potentially execute arb

high

How unsafe pickle deserialization happens in Keras/TensorFlow notebooks and how to fix it

A high-severity untrusted deserialization vulnerability was discovered in `TransferLearningTF.ipynb`, a transfer learning tutorial notebook that loads VGG16 model weights from the internet without verifying their integrity. Because Keras relies on Python's pickle-based serialization format under the hood, a tampered or substituted weights file could execute arbitrary code with the full privileges of the notebook user. The fix adds a SHA-256 checksum verification step immediately after the weight

high

How buffer overflow happens in C sprintf() and how to fix it

A high-severity buffer overflow vulnerability was discovered in `src/GL/arbgenerator.c` where `sprintf()` was used without size bounds checking on an 11-byte buffer. The fix replaces unsafe `sprintf()` calls with `snprintf()`, enforcing strict buffer boundaries and preventing potential heap corruption or code execution attacks.