jwt.verify accepts tokens with unrecognized `crit` header extensions (RFC 7515 §4.1.11)
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 3/5
- Tempo stimato
- 1-2 giorni
- Idoneità per principianti
- 48/100
- Tipo di issue
- Bug
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Tranquilla
- Stack tecnologico
- javascript, node.js
- Ambito
- authentication, security
Direzione di ricerca
Inizia in verify.js nel percorso decoded-header; esegui la riproduzione RSA fornita e confrontane il comportamento con RFC 7515 §4.1.11 e il riferimento validate_crit.ts di jose. Il lavoro è completato quando gli header crit non supportati o malformati vengono rifiutati durante la verifica e qualsiasi comportamento di opt-in del chiamante è coperto dai test.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Description
jsonwebtoken@9.0.3 accepts JWTs whose JOSE header contains a crit array listing extension Header Parameters that the library does not understand or process. Per RFC 7515 §4.1.11, such tokens must be rejected:
If any of the listed extension Header Parameters are not understood and supported by the recipient, then the JWS MUST be rejected.
A grep of the installed jsonwebtoken@9.0.3 source shows no crit handling at all — the field is silently ignored during verification. As a result, a signer who relies on crit to mandate that verifiers respect an extension (e.g. a key-binding or policy header) gets no enforcement when the verifier is jsonwebtoken, even though the signer marked the extension as critical.
Reproduction
// npm i jsonwebtoken@9.0.3
const jwt = require('jsonwebtoken');
const crypto = require('crypto');
const { publicKey, privateKey } = crypto.generateKeyPairSync('rsa', { modulusLength: 2048 });
const pubPem = publicKey.export ({ type: 'spki', format: 'pem' });
const privPem = privateKey.export({ type: 'pkcs8', format: 'pem' });
// Sign a token that declares an extension param as critical
const token = jwt.sign(
{ sub: 'x', role: 'admin' },
privPem,
{ algorithm: 'RS256',
header: { crit: ['x-attack-vector'], 'x-attack-vector': true } });
// Verify — RFC 7515 §4.1.11 requires rejection because jsonwebtoken does not
// understand or process the 'x-attack-vector' extension.
console.log(jwt.verify(token, pubPem, { algorithms: ['RS256'] }));
Observed output:
{ sub: 'x', role: 'admin', iat: 1779849601 }
Expected: a verification error (e.g. JsonWebTokenError: critical header parameter 'x-attack-vector' is not understood).
Cross-library comparison
jose@5.10.0 rejects the same token, citing the same RFC clause:
ERR_JOSE_NOT_SUPPORTED: Extension Header Parameter "x-attack-vector" is not recognized
So a deployment that issues tokens with crit-protected extensions via one library and verifies them with jsonwebtoken loses the protection the signer intended.
Why it matters
crit is the mechanism JWS provides for a signer to require that a particular extension header be honored. Concrete examples in the wild:
b64(RFC 7797) — signer asserts the payload is not base64url-encoded; a verifier ignoringcritwill treat it as encoded and either fail or, worse, validate a different payload than the one signed.- Custom security-policy extensions (e.g. token-binding hints, audience-restriction extensions, replay-protection nonces) where the signer explicitly demands enforcement.
A verifier that silently strips crit defeats the whole purpose of the field as defined in RFC 7515.
Suggested fix direction
In verify.js, after the header is decoded:
- If
header.critexists, it must be a non-empty array of strings (per §4.1.11). - Reject if
critlists any name that this library does not implement. Sincejsonwebtokendoes not implement anycritextensions, the simplest correct behavior is to reject any token whosecritis non-empty unless the caller opts in via an option likecrit: ['name1', ...]enumerating extensions the caller has handled out-of-band.
jose's implementation is a small reference.
Environment
jsonwebtoken9.0.3 (current latest on npm)- Node v26.0.0
- macOS 14
- Lingua principale
- JavaScript
- Stelle
- 18.2k
- Fork
- 1.3k
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di auth0/node-jsonwebtoken
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
auth0/node-jsonwebtoken#1042 · 1 commento ·
-
`jwt.sign()` callback is executed twice for "The payload already has an "..." property" errors Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
auth0/node-jsonwebtoken#1000 · 2 commenti · 1 reazione ·
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 65/100
auth0/node-jsonwebtoken#1046 ·
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 10/100
auth0/node-jsonwebtoken#1034 ·
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 48/100
auth0/node-jsonwebtoken#1031 ·
Tutte le issue di auth0/node-jsonwebtoken
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
-
area-deployment area-integrations triage:bot-seen
Difficoltà 2/5 Mezza giornata Idoneità per principianti 86/100
-
Issue-Bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
sugarlabs/musicblocks#8924 ·
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 90/100
ArduPilot/ardupilot_wiki#8088 ·
-
[BUG] createTool tools cannot be registered with Mastra when exactOptionalPropertyTypes is enabled Apertacustomer-eng status: needs triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100