Skip to content

fix: wrap crypto TypeError in JsonWebTokenError for malformed EC/RSA signatures#1018

Open
Vansh1811 wants to merge 1 commit intoauth0:masterfrom
Vansh1811:fix/wrap-crypto-typeerror-767
Open

fix: wrap crypto TypeError in JsonWebTokenError for malformed EC/RSA signatures#1018
Vansh1811 wants to merge 1 commit intoauth0:masterfrom
Vansh1811:fix/wrap-crypto-typeerror-767

Conversation

@Vansh1811
Copy link

Problem

When verifying a JWT signed with an EC (ES256, ES384, ES512) or RSA algorithm and the signature is malformed (e.g., truncated by one byte), jws.verify() can throw a raw TypeError from the underlying Node.js crypto module:

TypeError: "ES512" signatures must be "132" bytes, saw "131"

This TypeError is not a JsonWebTokenError and is passed directly to done(e). As a result:

  • Synchronous callers receive an undocumented TypeError instead of the expected JsonWebTokenError
  • Code that catches JsonWebTokenError to classify errors (e.g., returning 401 Unauthorized) will not catch this error
  • The error type is inconsistent with all other signature-validation failures, which return JsonWebTokenError('invalid signature')

Reproduction

const { sign, verify } = require('jsonwebtoken')

const JWT_PRIVATE_KEY = `-----BEGIN EC PRIVATE KEY-----
...ES512 key...
-----END EC PRIVATE KEY-----`

const JWT_PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----
...EC public key...
-----END PUBLIC KEY-----`

const token = sign({ foo: 'bar' }, JWT_PRIVATE_KEY, { algorithm: 'ES512' })

try {
  // Truncate the last byte of the signature
  verify(token.slice(0, -1), JWT_PUBLIC_KEY, { algorithms: ['ES512'] })
} catch (err) {
  console.log(err instanceof JsonWebTokenError) // false (should be true)
  console.log(err.constructor.name)             // TypeError (should be JsonWebTokenError)
  console.log(err.message)                      // 'ES512 signatures must be 132 bytes, saw 131'
}

Fix

In the jws.verify() catch block in verify.js, check if the thrown error is already a JsonWebTokenError. If it is not, wrap it in new JsonWebTokenError('invalid signature') before passing to done().

This ensures:

  • All signature-validation errors surface as JsonWebTokenError
  • The error message 'invalid signature' is consistent with valid-but-wrong-signature failures
  • Existing behaviour for JsonWebTokenErrors thrown by jws is preserved

Changes

  • verify.js: 3 lines changed in the jws.verify() catch block

Fixes #767

When verifying a JWT with EC or RSA algorithms, malformed signatures
could cause jws.verify() to throw a raw TypeError from the underlying
Node.js crypto module (e.g. 'ES512 signatures must be 132 bytes, saw 131')
instead of a JsonWebTokenError.

This TypeError was passed directly to done(e) and would surface to
callers as an undocumented error type, breaking any code that catches
JsonWebTokenError to handle invalid-signature scenarios.

Fix: in the jws.verify() catch block, check if the thrown error is
already a JsonWebTokenError; if not, wrap it in
new JsonWebTokenError('invalid signature') so callers always receive
the documented, consistent error type.

Fixes auth0#767
@Vansh1811 Vansh1811 requested a review from a team as a code owner March 25, 2026 10:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

verify throws undocumented TypeError for invalid input with algorithm: 'ES512', instead of a documented JsonWebTokenError

1 participant