CVE-2025-31123

8.7 HIGH

📋 TL;DR

Zitadel identity infrastructure software has a vulnerability where expired JWT keys can be used to obtain valid access tokens during Authorization Grants. This allows attackers with expired credentials to bypass authentication controls and gain unauthorized access. All Zitadel deployments using affected versions are vulnerable.

💻 Affected Systems

Products:
  • Zitadel
Versions: Versions before 2.71.6, 2.70.8, 2.69.9, 2.68.9, 2.67.13, 2.66.16, 2.65.7, 2.64.6, and 2.63.9
Operating Systems: All
Default Config Vulnerable: ⚠️ Yes
Notes: Only affects Authorization Grants endpoint; JWT Profile for OAuth 2.0 Client Authentication on Token and Introspection endpoints correctly rejects expired keys.

📦 What is this software?

⚠️ Risk & Real-World Impact

🔴

Worst Case

Attackers gain persistent unauthorized access to protected resources, potentially compromising user accounts, sensitive data, and administrative functions.

🟠

Likely Case

Attackers with previously obtained expired keys can regain access to systems they should no longer have access to, leading to privilege escalation and data exposure.

🟢

If Mitigated

With proper monitoring and short token lifetimes, impact is limited to brief unauthorized access windows before detection.

🌐 Internet-Facing: HIGH
🏢 Internal Only: MEDIUM

🎯 Exploit Status

Public PoC: ✅ No
Weaponized: UNKNOWN
Unauthenticated Exploit: ✅ No
Complexity: MEDIUM

Requires attacker to possess an expired JWT key; exploitation involves using standard OAuth flows with expired credentials.

🛠️ Fix & Mitigation

✅ Official Fix

Patch Version: 2.71.6, 2.70.8, 2.69.9, 2.68.9, 2.67.13, 2.66.16, 2.65.7, 2.64.6, or 2.63.9

Vendor Advisory: https://github.com/zitadel/zitadel/commit/315503beabd679f2e6aec0c004f0f9d2f5b53ed3

Restart Required: No

Instructions:

1. Identify your Zitadel version. 2. Upgrade to the appropriate patched version from the release tags. 3. Verify the fix by testing with expired JWT keys.

🔧 Temporary Workarounds

Rotate all JWT keys

all

Immediately rotate all JWT keys to invalidate any expired keys that attackers might possess

zitadel keys rotate --type=jwt

Implement external validation

all

Add external validation layer to check JWT key expiration before processing Authorization Grants

🧯 If You Can't Patch

  • Implement strict monitoring for Authorization Grant requests using expired keys
  • Reduce JWT key lifetimes and implement aggressive key rotation schedules

🔍 How to Verify

Check if Vulnerable:

Test by attempting to use an expired JWT key in an Authorization Grant request; if successful, system is vulnerable.

Check Version:

zitadel version

Verify Fix Applied:

Attempt the same test with expired JWT key; request should be rejected with proper expiration error.

📡 Detection & Monitoring

Log Indicators:

  • Authorization Grant requests succeeding with expired timestamps in JWT
  • Unusual token issuance patterns from known expired keys

Network Indicators:

  • Increased Authorization Grant requests with similar JWT signatures
  • Tokens issued outside normal patterns

SIEM Query:

source="zitadel" AND (message="authorization_grant" OR message="token_issued") AND jwt_exp < now()

🔗 References

📤 Share & Export