Claude-skill-registry jwt-attack-surface
Audit JWT implementation for algorithm confusion, secret weakness, claim validation issues, and token handling vulnerabilities. Use when reviewing authentication systems using JWT.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/jwt-attack-surface" ~/.claude/skills/majiayu000-claude-skill-registry-jwt-attack-surface && rm -rf "$T"
manifest:
skills/data/jwt-attack-surface/SKILL.mdsource content
JWT Attack Surface Audit
Purpose
Identify JWT implementation vulnerabilities including algorithm confusion, weak secrets, missing validation, and token handling issues.
Focus Areas
- Algorithm Confusion: alg=none, RS256→HS256 confusion
- Weak Secrets: Short/guessable HMAC secrets
- Missing Validation: Signature bypass, claim verification
- Token Handling: Storage, transmission, revocation
- Claim Issues: Expiration bypass, privilege escalation
Critical Vulnerabilities
Algorithm None Attack
// VULNERABLE - accepts "alg": "none" jwt.verify(token, secret, { algorithms: ['HS256', 'none'] }); // SECURE - explicit algorithm whitelist jwt.verify(token, secret, { algorithms: ['HS256'] });
RS256 to HS256 Confusion
# If server uses RS256 (asymmetric): # - Attacker gets public key # - Signs token with public key using HS256 # - Server verifies with public key as HMAC secret # VULNERABLE - accepts multiple algorithms jwt.decode(token, public_key, algorithms=['RS256', 'HS256']) # SECURE - single algorithm only jwt.decode(token, public_key, algorithms=['RS256'])
Weak HMAC Secret
// VULNERABLE - short/guessable secret const secret = "secret123"; jwt.sign(payload, secret); // SECURE - strong random secret (>= 256 bits) const secret = crypto.randomBytes(64).toString('hex');
Missing Expiration Check
// VULNERABLE - ignoring exp claim claims, _ := jwt.Parse(token, keyFunc) // No expiration validation! // SECURE - validate expiration claims, err := jwt.ParseWithClaims(token, &Claims{}, keyFunc) if err != nil || claims.ExpiresAt.Before(time.Now()) { return ErrExpired }
Output Format
findings: - title: "JWT accepts 'none' algorithm" severity: critical attack_scenario: "Attacker crafts unsigned JWT with alg=none, bypasses authentication" preconditions: "None" reachability: public impact: "Complete authentication bypass" confidence: high cwe_id: "CWE-327" affected_assets: - "src/auth/jwt.rs:45" - "/api/auth/verify"
Audit Checklist
Token Generation
[ ] Secret is cryptographically random (>= 256 bits) [ ] Algorithm is explicitly set (not from token) [ ] Claims include: iat, exp, iss, aud [ ] Expiration is reasonable (< 24h for access tokens) [ ] Sensitive data not in payload (use references)
Token Verification
[ ] Algorithm whitelist (single algorithm preferred) [ ] Signature verification BEFORE parsing claims [ ] Expiration (exp) validated [ ] Issuer (iss) validated [ ] Audience (aud) validated [ ] Not-before (nbf) validated if present
Token Handling
[ ] Stored in httpOnly cookie (not localStorage) [ ] Transmitted over HTTPS only [ ] Revocation mechanism exists [ ] Refresh token rotation implemented [ ] Token not leaked in URLs/logs
Attack Scenarios
1. None Algorithm
Header: {"alg": "none", "typ": "JWT"} Payload: {"sub": "admin", "role": "admin"} Signature: (empty)
2. Key Confusion (RS256→HS256)
# Get public key from /api/.well-known/jwks.json # Sign with public key using HS256 # Server uses public key as HMAC secret
3. Weak Secret Brute Force
# Tools: hashcat, jwt_tool hashcat -m 16500 jwt.txt wordlist.txt
4. Claim Tampering
# Modify claims if signature not verified {"sub": "user", "role": "user"} → {"sub": "admin", "role": "admin"}
Severity Guidelines
| Issue | Severity |
|---|---|
| alg=none accepted | Critical |
| Algorithm confusion possible | Critical |
| Weak/guessable secret | Critical |
| No signature verification | Critical |
| No expiration validation | High |
| Token in URL/logs | High |
| No issuer/audience validation | Medium |
| Token in localStorage | Medium |
| Long expiration (> 24h) | Low |
KYCo Integration
Register JWT implementation vulnerabilities:
1. Check Active Project
kyco project list
2. Register Finding
kyco finding create \ --title "JWT accepts 'none' algorithm" \ --project PROJECT_ID \ --severity critical \ --cwe CWE-327 \ --attack-scenario "Attacker crafts unsigned JWT with alg=none, bypasses authentication" \ --impact "Complete authentication bypass" \ --assets "src/auth/jwt.rs:45,/api/auth/verify"
3. Import Scanner Results
# Import semgrep JWT rules semgrep --config p/jwt --sarif -o jwt-audit.sarif . kyco finding import jwt-audit.sarif --project PROJECT_ID
Common CWE IDs for JWT Issues
- CWE-327: Use of Broken or Risky Cryptographic Algorithm
- CWE-287: Improper Authentication
- CWE-347: Improper Verification of Cryptographic Signature
- CWE-798: Use of Hard-coded Credentials (weak secret)
- CWE-613: Insufficient Session Expiration