JWT Vulnerabilities Beyond alg:none: What Pentesters Actually Find in Production | Lorikeet Security Skip to main content
Back to Blog

JWT Vulnerabilities Beyond alg:none: What Pentesters Actually Find in Production

Lorikeet Security Team March 12, 2026 9 min read

TL;DR: The alg:none JWT attack is thoroughly documented and patched in modern libraries. What actually gets exploited in production is subtler: the algorithm confusion attack where an RS256 token is forged using the server's public key as an HMAC secret, brute-forceable weak signing secrets in early-stage applications, kid parameter injection, and missing server-side token lifecycle enforcement. These findings routinely result in complete authentication bypass and privilege escalation.

The Severity Landscape: What's Actually Exploitable

JWT Vulnerability Severity Frequency in Production Impact
Algorithm Confusion (RS256 → HS256) Critical Low–Medium (library-dependent) Full authentication bypass, forge any user's token
Weak/Guessable HMAC Secret Critical Medium (especially in early-stage apps) Full authentication bypass, forge any user's token
kid Parameter Injection Critical Low SQL injection or path traversal to control signing key
Missing Expiry Enforcement (exp) High High Persistent account access after logout or password change
No Signature Validation Critical Low (rare but catastrophic) Complete authentication bypass — no cracking needed
localStorage Token Storage High Very High Token theft via any XSS — full account takeover
Refresh Token Reuse After Logout High High Persistent access after user-initiated logout

Algorithm Confusion: The Most Dangerous JWT Attack

The algorithm confusion attack exploits a fundamental design tension in JWT: the token header specifies which algorithm was used to sign it, and some JWT library implementations trust this claim when verifying the signature rather than enforcing the algorithm the server expects.

The attack works specifically against applications using RS256 (RSA public/private key pair) signatures. The server's RSA public key is, by definition, public — it may be served at a JWKS endpoint, embedded in documentation, or discoverable through standard OIDC discovery metadata. An attacker who can obtain the public key attempts the following:

  1. Obtain a legitimate JWT token from the application
  2. Decode the header and change the algorithm from RS256 to HS256
  3. Modify the payload — escalating privileges, changing user ID, etc.
  4. Sign the modified token using the server's RSA public key as the HMAC secret
  5. Submit the forged token

If the JWT library trusts the alg header rather than enforcing RS256, it switches to HMAC verification — and the signature passes, because both sides are now using the same key (the public key) for the same operation (HMAC-SHA256).

Remediation: Configure JWT verification to explicitly specify the expected algorithm — never derive it from the token header. Use libraries that enforce algorithm whitelisting at the verification step.


Brute-Forceable Weak HMAC Secrets

HMAC-signed JWTs (HS256, HS384, HS512) are only as secure as the signing secret. Early-stage applications frequently use short, predictable secrets set during initial development: the application name, secret, jwt_secret, 1234567890, or an environment variable that was never set and defaults to an empty string.

Offline cracking is the attack: the attacker captures a valid JWT from the application and runs it through a cracking tool with a wordlist. If the secret is in the wordlist, cracking takes seconds. With the secret in hand, the attacker can forge tokens for any user in the system — including administrative accounts — without any server interaction.

Finding method: Pentesters extract captured tokens and run them against common JWT secret wordlists. Any successful crack is a critical-severity finding regardless of the application's maturity.

Remediation: Use cryptographically random secrets of at least 256 bits (32 bytes) for HMAC-signed JWTs. Prefer RS256 or ES256 (asymmetric signatures) for tokens that cross trust boundaries — the signing key never leaves the issuer, and verification uses the public key only. Rotate secrets on any suspected exposure event.


kid Parameter Injection

The JWT header may include a kid (Key ID) parameter indicating which key should be used to verify the signature. If the server uses this parameter to look up the signing key from a database or filesystem, and the parameter is not sanitized before use in a query or file operation, it can be exploited for SQL injection or path traversal.

A SQL injection in the kid parameter can be used to return an attacker-controlled string as the "signing key" — allowing the attacker to forge tokens signed with a key of their choosing. A path traversal (kid: "../../dev/null" or similar) may allow the attacker to specify a predictable file as the key material.

Remediation: Never use user-controlled JWT header parameters directly in database queries or filesystem operations. Validate kid values against a fixed whitelist of known key identifiers.


Missing Server-Side Expiry Enforcement

JWTs contain an exp claim specifying when the token expires. Many applications configure a reasonable expiry in the token — 15 minutes, 1 hour — but fail to enforce it server-side. The token validation logic checks the signature but skips the expiry check, accepting tokens long after their stated expiry.

This becomes a persistent access vulnerability: once an attacker obtains a valid token — through XSS, a compromised session, a logged request — they retain access indefinitely, regardless of whether the victim subsequently changes their password or the application "revokes" the token in its own records. The signed token remains valid at the API level.

Related finding: Many applications implement a logout mechanism that deletes the token client-side but does not maintain a server-side revocation list. The deleted token continues to work if presented directly to the API — a common finding in applications where logout is critical to the security model (e.g., shared workstations, compliance requirements for session termination).

Remediation: Enforce the exp claim in all JWT validation logic. For high-security requirements, maintain a short-lived token with server-side revocation capability — a token blocklist or a database-backed session record that can be invalidated on logout or password change.


Token Storage in localStorage

Storing JWTs in localStorage or sessionStorage is extremely common in single-page applications — it's the simplest implementation and works well in the happy path. The vulnerability is XSS: any JavaScript injection vulnerability anywhere on the domain allows the attacker to read localStorage and exfiltrate the access token with a single line of code.

At Lorikeet Security, our web application assessments consistently identify localStorage token storage in SPA applications. When combined with even a low-severity XSS finding — stored XSS in a comment field, reflected XSS in an error parameter — the combined severity escalates to critical: authentication bypass via token theft.

Remediation: Store access tokens in httpOnly, Secure, SameSite=Strict cookies. JavaScript cannot read httpOnly cookies, so XSS cannot exfiltrate them. Refresh tokens in particular should always use httpOnly cookies rather than in-memory or localStorage storage.


Refresh Token Rotation Failures

Many applications implement refresh tokens to extend sessions without re-authentication. The security model depends on refresh tokens being single-use with rotation: when a refresh token is used to get a new access token, the old refresh token is invalidated and a new one is issued. If rotation is not enforced — or if the old token is not properly invalidated on the server — a stolen refresh token provides persistent access even after the legitimate user logs out and obtains a new token through the rotation process.

Pentesters test this by capturing a refresh token, allowing the legitimate session to proceed normally (triggering rotation), then attempting to use the captured original token. If it still works, rotation is not being enforced server-side.

For a comprehensive review of your application's authentication implementation — including JWT handling, token lifecycle management, and session security — book a web application penetration test with Lorikeet Security. Our web app assessments cover the full OWASP Top 10 and all common JWT vulnerabilities with manual testing that automated scanners cannot replicate.

Validate Your Application's Authentication Security

Lorikeet Security's web application penetration testing includes comprehensive JWT and authentication testing — algorithm confusion, secret strength, token lifecycle, storage security, and session management. Book a consultation to get started.

-- views
Link copied!
Lorikeet Security

Lorikeet Security Team

Penetration Testing & Cybersecurity Consulting

We've completed 170+ security engagements across web apps, APIs, cloud infrastructure, and AI-generated codebases. Everything we publish here comes from patterns we see in real client work.

Lory waving

Hi, I'm Lory! Need help finding the right service? Click to chat!