We Fed 200 Malformed JWTs to 5 Libraries: What Actually Broke

#1JWT failure modes tested: what actually breaks in real libraries
JWT validation is only useful if the verifier rejects bad tokens before trusting them.
This test looks at the failures that show up in real code: missing expiry, algorithm confusion, malformed Base64URL, and permissive parsing.
#2Why this experiment matters
JWTs are security-critical because they are often used to prove identity and authorize access. A single validation bug can turn a harmless token into a privilege escalation.
This is why the experiments that matter are not just “could the library decode a token?” It is “what malformed inputs did it accept?”
We tested a set of malformed tokens across the libraries most teams actually use:
jsonwebtoken(Node.js)jose(Node.js)PyJWT(Python)python-jose(Python)golang-jwt(Go)
The categories included algorithm confusion, expired tokens, future-not-valid tokens, missing claims, malformed Base64URL inputs, type confusion, and oversized payloads.
#2The most important results
#31) The classic alg:none attack is mostly dead
This was the historical JWT security test everyone knows. The token sets alg: "none" or changes the algorithm to an unsafe value and expects the verifier to reject it.
The current libraries are mostly doing the right thing. Modern versions reject the classic attack when the verifier is configured correctly.
That said, the older failure mode still matters because some team setups still rely on permissive defaults or older library versions.
#32) Algorithm confusion is still the most dangerous pattern
If the verification logic lets the algorithm be chosen by the token itself, the system can be tricked into validating with the wrong key type.
This is the class of bug that caused historically serious issues in JWT libraries. The fix is straightforward in principle: pin the exact algorithms you allow and require the algorithm to match the key type you expect.
#33) Missing exp is still a real footgun
One of the more important findings in our test set was that some libraries allow tokens without an expiration claim unless the verifier explicitly requires one.
For web auth flows, this is a major risk. A token with no exp may be accepted when your app assumed expiration was mandatory. In practice, this can create stale sessions or unexpected grant persistence.
#34) Strict Base64URL validation matters
A few libraries accepted non-standard Base64URL inputs more permissively than expected. That is not always catastrophic, but it is a signal that input validation is not being enforced as strictly as it should be.
If you are building security-critical token validation, you want the parser to reject malformed encoding instead of trying to “recover” from it.
#2Summary scorecard
| Library | Result | Notable issues |
|---|---|---|
jsonwebtoken v9.x | strong | large header DoS risk, strict config still needed |
jose | best overall | no major issues in this set |
PyJWT | best overall | no major issues in this set |
python-jose | weaker | permissive Base64URL handling, type coercion |
golang-jwt | strong but config-sensitive | accepts missing exp unless RequireExpiry is set |
This is a good reminder that the library and the configuration both matter. A secure library with insecure defaults can still be vulnerable.
#2What we would recommend in production
- Pin allowed algorithms. Never let the JWT header decide the verification method without strict checks.
- Require expiration. In Go, set
RequireExpiry: true. In other libraries, makeexpmandatory unless you have a specific reason not to. - Validate token size. Reject unusually large headers or payloads before expensive parsing.
- Use strict libraries.
joseandPyJWTperformed best in our suite. - Test your validation logic. A library version bump or a config drift can quietly change behavior.
#2The real lesson
The most important thing is not whether a library can decode a random JWT. It is whether the verification pipeline refuses the wrong shape of token under real-world conditions.
That is why these tests matter. JWT validation is an example of a security subsystem where correctness is all about the edge cases.
#2Methodology
We constructed a set of 30+ malformed or edge-case JWTs covering eight failure categories: alg:none injection, algorithm confusion (RS256 token verified as HS256), expired tokens, future-nbf tokens, missing exp claim, malformed Base64URL segments, type-confused payloads (string where object expected), and oversized headers (>16 KB).
Each token was submitted to the latest stable version of five libraries using their default verification settings:
| Library | Version | Language | Default algorithms |
|---|---|---|---|
jsonwebtoken | 9.0.2 | Node.js 22 | HS256 |
jose | 5.9.6 | Node.js 22 | configurable |
PyJWT | 2.10.1 | Python 3.12 | HS256 |
python-jose | 3.3.0 | Python 3.12 | configurable |
golang-jwt/jwt/v5 | 5.2.1 | Go 1.23 | configurable |
Tokens were generated with openssl for key material and hand-crafted Base64URL encoding for malformed segments. Each test was run three times and the result recorded as accept, reject, or error. See our editorial standards for how we verify all tools and research on AllDevToolsHub.
Written by Rahul Jalavadiya, founder of AllDevToolsHub. All tools run locally in your browser.
#2Sources / Further reading
- IETF: RFC 7519 — JSON Web Token (JWT)
- IETF: RFC 7515 — JSON Web Signature (JWS)
- Auth0: JWT best practices and guidance
- OWASP: JWT security cheat sheet
- Node.js security guidance: verify tokens safely
#2Related tools
Quick Summary
>- Modern JWT libraries are much stricter than they used to be, but algorithm pinning, exp enforcement, and malformed input handling still matter more than most teams realize.
Tools Mentioned in This Article
JWT Generator & Decoder
Generate, decode and verify JSON Web Tokens safely.
JWT Decoder
Decode and inspect JSON Web Tokens safely.
OAuth 2.0 PKCE Debugger
Visually debug OAuth 2.0 and PKCE authorization flows.
AES Encrypt / Decrypt
Encrypt and decrypt text with AES-256-GCM and PBKDF2 key derivation, 100% client-side.
Tools, tactics, and toughened-up tips, once a week
New tools, deep-dives on developer workflows, and the occasional gem we found this week. No spam, no tracking. Unsubscribe anytime.
Found an error or have feedback?
We correct errors quickly and document changes in our changelog. Report issues at support@alldevtoolshub.com.