Decode and inspect JSON Web Tokens (JWT) with ease
Understanding common JWT vulnerabilities helps you build more secure applications.
Attack: Attacker changes the algorithm to "none" and removes the signature, creating an unsigned token that vulnerable servers might accept.
Example: {"alg": "none", "typ": "JWT"}
Defense: Always explicitly specify and enforce accepted algorithms. Never accept "none" in production.
Attack: Server expects RS256 (public/private key) but attacker changes to HS256 (symmetric key) and signs with the public key, which the server might use to verify.
Why it works: The server's public key becomes the HMAC secret, allowing attackers to forge valid signatures.
Defense: Explicitly verify the algorithm matches expectations. Don't let the token dictate which algorithm to use.
Attack: For HMAC algorithms (HS256/384/512), attackers can brute-force weak secrets to forge valid tokens.
Weak secrets: "secret", "password", short keys, dictionary words
Defense: Use strong, random secrets (256+ bits). Consider using RS256/ES256 instead to avoid sharing secrets.
Attack: Tokens without expiration claims (exp) or servers that don't validate expiration remain valid forever.
Impact: Stolen tokens can be used indefinitely, even after logout or password change.
Defense: Always include and validate exp claim. Implement token refresh strategies. Consider short lifespans (minutes to hours).
Attack: Some JWT libraries only decode tokens without verifying signatures by default, allowing attackers to modify claims.
Impact: Attackers can change user IDs, roles, permissions, or any claim data.
Defense: Always use verify() or similar methods that validate signatures. Never trust decoded claims without verification.
Attack: JWT headers can include jku (JWK Set URL) or x5u (X.509 URL) pointing to key sources. Attackers can point these to malicious servers.
Impact: Server fetches attacker's keys and validates their forged tokens.
Defense: Don't trust jku/x5u headers. Use hardcoded or allowlisted key sources only.
Attack: The "kid" header specifies which key to use for verification. Poorly implemented servers might use this unsafely (e.g., file path traversal).
Example: "kid": "../../public.key"
Defense: Validate kid against an allowlist. Never use it directly for file system operations.
Attack: If tokens are stored in localStorage or accessible to JavaScript, XSS attacks can steal them.
Impact: Attacker gains full access to user account with stolen token.
Defense: Store tokens in httpOnly cookies when possible. Implement strong CSP headers. Sanitize all user input. Use short expiration times.