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.md
source 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

IssueSeverity
alg=none acceptedCritical
Algorithm confusion possibleCritical
Weak/guessable secretCritical
No signature verificationCritical
No expiration validationHigh
Token in URL/logsHigh
No issuer/audience validationMedium
Token in localStorageMedium
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