Listen to this Post
How GHSA-cjw9-ghj4-fwxf works:
The vulnerability resides in fast-jwt’s claim validation when `allowedAud` (or allowedIss, allowedSub, allowedJti, allowedNonce) is configured with a RegExp object instead of a string. The library evaluates the JWT’s `aud` claim against this RegExp. An attacker controls the `aud` claim and can craft a value like "a".repeat(n) + "Y". If the RegExp contains nested quantifiers (e.g., /^(a+)+X$/), the JavaScript regex engine enters catastrophic backtracking. The regex tries to match the repeated `a` groups against the trailing Y, failing exhaustively. Each additional character doubles the backtracking steps. Verification time grows exponentially with input length. At n=30, verification takes ~7.85 seconds, blocking Node.js event loop. This occurs after signature verification, so a valid JWT is required. Exploitation does not need pre-authentication, but any authenticated endpoint that verifies tokens becomes vulnerable. The attacker sends a legitimately signed JWT with a maliciously long `aud` claim. The library’s default behavior does not limit regex complexity or claim length. The root cause is CWE-1333 (Inefficient Regular Expression) combined with attacker-controlled input. The patch introduces regex complexity checks and length limits.
dailycve form:
Platform: Node.js fast-jwt
Version: 6.1.0 and below
Vulnerability: ReDoS via allowedAud
Severity: High
date: 2024-05-30
Prediction: Patch already released 2024-06-03
What Undercode Say:
Test vulnerable version npm install [email protected] node -e "const { verifier } = require('fast-jwt'); const verify = verifier({ allowedAud: /^(a+)+X$/ }); const malicious = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJhYWFhYWFhYWFhYWFhYWFhYWFhWSIsImlhdCI6MTUxNjIzOTAyMn0.sign'; console.time('verify'); try { verify(malicious); } catch(e) {} console.timeEnd('verify');" Expected output: ~7.8 seconds for 30 chars
Check if your RegExp is vulnerable using regex安全检查工具
npm install safe-regex
node -e "const safe = require('safe-regex'); console.log(safe(/^(a+)+X$/));" returns false
Exploit:
Craft a valid JWT with `aud` claim set to "a".repeat(30) + "Y". Use any HS256/RS256 secret (if known or leaked). Send to endpoint that verifies tokens with vulnerable regex. Single request consumes CPU for ~8 seconds. Multiple parallel requests saturate event loop, causing denial of service.
Protection from this CVE
Upgrade to fast-jwt >=6.2.1. If unable, replace RegExp objects with plain strings. For required regex, enforce `safe-regex` validation or limit claim length to <20 characters. Use `--max-http-header-size` and timeout middleware.
Impact:
CPU exhaustion, event loop blocking, API throughput degradation, cascading failures in microservices, increased serverless costs, authentication infrastructure saturation. Verified 24 chars → 123ms, 28 chars → 1.97s, 30 chars → 7.85s.
🎯Let’s Practice Exploiting & Learn Patching For Free:
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

