A JSON Web Token looks tamper-proof — it's signed, after all — but a lot of real-world (and CTF) JWT bugs come from how a server verifies that signature, not the token format itself. jwt_tool automates probing for the common ways that verification goes wrong, instead of manually re-encoding base64url segments by hand every time you want to test a theory.
Decoding a token and inspecting its claims
python3 jwt_tool.py eyJhbGciOiJIUzI1NiIs...
Run with no attack flags, jwt_tool just decodes and pretty-prints the header and payload — the fastest way to see the algorithm (alg), what claims it carries (role, exp, sub...), and whether anything in there looks worth tampering with, like a "role": "user" field.
Testing the alg=none attack
python3 jwt_tool.py eyJhbGciOiJIUzI1NiIs... -X a
Some JWT libraries will accept a token whose header says "alg": "none" and skip signature verification entirely. -X a generates that variant automatically from your original token — if the server accepts it, you've just found you can forge arbitrary claims with no secret at all.
Brute-forcing a weak HMAC secret
python3 jwt_tool.py eyJhbGciOiJIUzI1NiIs... -C -d wordlist.txt
If the token uses HS256, the signature is just an HMAC with a secret key — and if that secret is weak ("secret", "changeme", the app's name), it's crackable the same way a password hash is. -C -d tries every word in a wordlist as the signing key and reports which one, if any, produces a matching signature.
Tampering a claim and re-signing
python3 jwt_tool.py eyJhbGciOiJIUzI1NiIs... -T
-T opens an interactive mode to edit individual claims (like flipping "role": "user" to "role": "admin") and then re-sign the result — using a secret you've recovered, or testing whether the server even checks the signature on certain requests at all.
Why it's worth learning
None of jwt_tool's attacks work against a correctly implemented JWT — a strong secret, a server that actually enforces the expected algorithm, and no acceptance of alg=none defeat all of them. That's exactly why it's useful: running through its standard checks quickly tells you whether a CTF's auth is solid or has one of these well-known holes, instead of testing each one by hand against a token you're re-encoding manually every time.