Break six synthetic tokens, watch an unsafe verifier accept them, then compare the exact validation rule that blocks each failure. All keys, signatures and dictionary attempts stay in this browser.
The attacker changes the claims and removes the signature. A verifier that trusts the header's algorithm treats the token as intentionally unsigned.
{{noneError}}
{{noneResult.token}}role: admin claim reaches authorization. acceptedFix: configure an explicit algorithm allowlist, reject none, and verify the signature before using the payload.
The lab creates a fresh RSA key pair, then signs an HS256 token with the public key text as the HMAC secret. A confused verifier accepts it because it chooses the algorithm from the token.
The private key is never displayed or persisted. Generate a new pair for every run.
{{confusionError}}
{{confusionOutput}}Fix: bind each issuer and key to one allowed algorithm. Never derive verification behavior from an untrusted alg header.
The untrusted kid header is concatenated into a server key path. This browser lab resolves that path against a tiny mock filesystem, never the device running it.
{{kidError}}
{{kidResult.token}}Fix: treat kid as an opaque identifier into a server-side allowlist. Do not pass it to filesystem or URL path construction.
A signed token is only as strong as its HMAC secret. The worker tests the local wordlist without freezing the interface or sending the token anywhere.
Maximum 50,000 non-empty candidates per run.
{{weakError}}
{{weakFound}} Fix: generate at least 256 random bits for HS256, rotate exposed secrets, and prefer asymmetric signing when verifiers should not receive signing authority.
The signature remains mathematically valid after exp. A verifier that checks only the signature silently turns a short-lived bearer token into a permanent credential.
{{replayResult.token}}{{replayError}}
{{replayResult.temporal.reasons.join(', ')}}. Issuer and audience must also match the endpoint policy.rejectedFix: validate exp, nbf, issuer and audience on every request. Use short TTLs and a revocation or token-version strategy where immediate invalidation matters.
The token's jku header names the URL its public key comes from. A verifier that fetches whatever URL the token supplies lets an attacker publish their own key and point straight at it. This lab never fetches any URL — the "server" the vulnerable and safe paths consult is a two-entry in-memory map, so the concept is reproduced without a single request leaving this tab.
A fresh RSA pair signs the token; a second, unrelated RSA pair plays the real issuer. Neither key is displayed or leaves this page.
{{jkuError}}
{{jkuResult.forgedToken}}jku/x5u header is never read; only the server's own configured JWKS URL is ever consulted.{{jkuResult.safeAccepted?'accepted':'rejected'}}Fix: never fetch a key from a URL the token itself supplies. Pin verification to your own configured JWKS endpoint (or a short server-side allowlist), and treat jku/x5u as informational at most.
kid inside an explicit key map.jku/x5u lookups to a server-configured URL, never the token's own claim.This page uses Web Crypto for HMAC and RSA operations. The weak-secret run executes in a Web Worker. No fetch, analytics call, local storage or server endpoint receives your token, candidates or generated keys.
The path traversal scenario uses a two-entry JavaScript object as a mock filesystem. It cannot read a local file or a server path. The jku SSRF scenario is the same idea applied to key URLs: a two-entry in-memory Map stands in for a JWKS server, and neither the vulnerable nor the safe verifier path ever makes a network request — the "attacker" URL is never actually requested, anywhere.
Test only systems and tokens you own or are explicitly authorized to assess.