Break five 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.
Use this playground for learning and for tokens you are authorized to test.The RSA key pair, mock filesystem and weak secrets below are generated for this page. The lab never contacts a target, reads a real server path or stores pasted tokens.
01
Unsigned token accepted as alg:none
The attacker changes the claims and removes the signature. A verifier that trusts the header's algorithm treats the token as intentionally unsigned.
Forged claims
{{noneError}}
{{noneResult.token}}
Verifier decision
Trust header algNo signature is checked. The forged role: admin claim reaches authorization.accepted
Pinned algorithmThe server requires its configured algorithm before it reads any claim.rejected
Fix: configure an explicit algorithm allowlist, reject none, and verify the signature before using the payload.
02
HS256 and RS256 key confusion
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.
Ephemeral key lab
The private key is never displayed or persisted. Generate a new pair for every run.
{{confusionError}}
{{confusionOutput}}
Verifier decision
Trust token algThe verifier reuses the RSA public key bytes as an HMAC secret when the forged header says HS256.accepted
Expect RS256The forged token never reaches RSA verification because its algorithm does not match policy.rejected
Forged HS256{{confusionResult.vulnerableAccepted?'accepted by confused verifier':'failed'}}
Pinned verifier{{confusionResult.safeAccepted?'accepted':'rejected before key use'}}
Fix: bind each issuer and key to one allowed algorithm. Never derive verification behavior from an untrusted alg header.
No key pair yetRun the local demo to compare both verifier paths.
03
kid path traversal
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.
Header value
{{kidError}}
{{kidResult.token}}
Mock lookup trace
key root/var/app/keys/
untrusted kid{{kidValue}}
resolved path{{kidResult.resolvedPath}}
mock read{{kidResult.lookupSucceeded?'file content used as HMAC key':'no matching mock file'}}
Path concatenationThe key loader normalizes a user-controlled path and trusts the returned bytes.{{kidResult.vulnerableAccepted?'accepted':'not reached'}}
Key ID map{{kidResult.safeReason}}{{kidResult.safeAccepted?'accepted':'rejected'}}
Fix: treat kid as an opaque identifier into a server-side allowlist. Do not pass it to filesystem or URL path construction.
04
Weak HS256 secret recovery
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.
HS256 token
Candidate secrets · one per line
Maximum 50,000 non-empty candidates per run.
Worker run
{{weakAttempts}} / {{weakTotal}} attempts
{{weakStatus}}{{weakRate}}
{{weakError}}
Recovered secret{{weakFound}}
Fix: generate at least 256 random bits for HS256, rotate exposed secrets, and prefer asymmetric signing when verifiers should not receive signing authority.
05
Expired token replay
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.
Signature onlyThe HMAC matches, so the stale bearer credential is replayed successfully.accepted
Full claims policy{{replayResult.temporal.reasons.join(', ')}}. Issuer and audience must also match the endpoint policy.rejected
Fix: validate exp, nbf, issuer and audience on every request. Use short TTLs and a revocation or token-version strategy where immediate invalidation matters.
What this lab proves
JWT decoding is not trust. Header and payload are untrusted input until verification succeeds.
Signature verification is not enough. Algorithm, key, issuer, audience and temporal claims are one policy.
Convenient dynamic key lookup expands the attack surface. Keep kid inside an explicit key map.
Bearer tokens can be replayed. Short expiry limits damage but does not replace secure transport and storage.
Privacy and scope
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.
Test only systems and tokens you own or are explicitly authorized to assess.