Urgent.News

What's breaking now, across thousands of outlets.

Tech

Why Cursor Decodes JWTs Instead of Verifying Them (CWE-347)

TL;DR AI editors regularly write auth middleware that calls jwt.decode() where it needs jwt.verify() , so the token's signature is never checked. Anyone can then edit the payload, set "role": "admin" , and walk in. The forged token never has to be signed. The fix: verify every token with a pinned algorithm list, and use jose where jsonwebtoken will not run. I asked Cursor to add route protection…

Why Cursor Decodes JWTs Instead of Verifying Them (CWE-347)

AI editors often write authentication middleware that uses jwt.decode() when they should be using jwt.verify(). This allows anyone to modify the payload, change the role to admin, and gain unauthorized access. The forged token doesn't need to be signed. The solution is to verify every token with a list of authorized algorithms and use the jose library instead of jsonwebtoken, which fails to verify signatures on untrusted messages.

When the reporter asked Cursor to add route protection to a Next.js app, the first version imported jsonwebtoken into middleware.ts. The build failed due to the Edge runtime lacking the Node crypto module. Cursor fixed the build error by swapping jwt.verify() for jwt.decode(), making the protected pages redirect logged-out users. Manual tests passed, giving the impression that a working auth layer was in place.

However, decoding a JWT without verifying its signature leaves the system vulnerable to attacks. The middleware checks expiration and role, but a malicious user can decode the token, change the role to admin, extend the expiration, re-encode the token, and paste it back into the cookie. Since the signature no longer matches, nothing checks, and the user gains unauthorized access.

Using decode() is a shortcut that makes the error disappear from the editor's perspective. They use functions with similar names and imports, and both return the same payload for legitimate tokens. Security controls are invisible when everything is working correctly, so no one writes a test case for forged tokens while trying to get the build to pass. The editor's training data also contains many examples of using decode() correctly, such as displaying user IDs on the client.

Older versions of jsonwebtoken (8.5.1 and below) were particularly susceptible to this vulnerability. If the verify() function was called without specifying algorithms, it could fall back to the "none" algorithm, accepting unsigned tokens. This issue was fixed in version 9.0.0, but many editors still use older versions, introducing the same vulnerability.

To fix the issue, every request that makes an authentication decision should have its signature verified, and the algorithm used should be pinned. Failure should be closed on any error. In the case of Next.js middleware on the Edge runtime, the jose library should be used, which runs on Web Crypto.

Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.

Read the original at dev.to →

More in Tech

WildNotes - Wonder that grows with you

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass What I Built Most modern nature applications suffer from a quiet paradox: they claim to connect us with the…

  • WildNotes reconnects users with nature offline
  • Encourages sensory engagement with outdoor elements
  • Promotes mindfulness through deep breathing and contemplation

How I keep Cloudflare under $5 (and what quietly runs up your bill)

I run a few sites on Cloudflare's $5 Workers plan. The base plan covers a lot more than people expect. Most of the surprise bills I've read about come from a few products doing far more work than…

  • Cloudflare's $5 Workers plan includes 10 million requests and 30 million CPU milliseconds per month
  • Enable billing notifications to avoid surprise charges from resource-intensive applications
  • Serve static files directly to take advantage of free and unlimited usage

More from Saturday 10 October →