Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

Bug: clockTolerance accepts arbitrarily large values, bypassing exp verification entirely

Aperta
#1,021 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

@abhu85 ci sta già lavorando.

Dal 22/6/2026.

  • #1036 di @abhu85 — aperta
  • #1039 di @Pranav18M — aperta

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
52/100
Tipo di issue
Bug
Chiarezza
Abbastanza chiara
Stato di attività
Tranquilla
Stack tecnologico
javascript, node.js

Direzione di ricerca

Inizia in verify.js, tracciando la validazione di clockTolerance e i confronti di exp/nbf. Conferma con i maintainers il limite superiore supportato e il comportamento degli errori, quindi aggiungi una copertura di regressione mirata per una tolleranza eccessiva e per entrambi i controlli. Il lavoro è completo quando i valori elevati vengono rifiutati senza indebolire la gestione normale del clock-skew.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Summary

The clockTolerance option in verify() accepts any positive integer with no upper bound validation. Passing Number.MAX_SAFE_INTEGER (or any value large enough that exp + clockTolerance overflows to Infinity) causes the expiry check to silently pass for any expired token, regardless of how long ago it expired.

Environment

  • jsonwebtoken version: 9.0.3 (latest)
  • Node.js: v20+

Reproduction

const jwt = require("jsonwebtoken");
const SECRET = "supersecret";

// Sign a token that expired 1 year ago
const expiredToken = jwt.sign(
  { sub: "user", role: "admin" },
  SECRET,
  { expiresIn: "-365d" }
);

// Normal verify correctly rejects it
try {
  jwt.verify(expiredToken, SECRET);
} catch (e) {
  console.log(e.message); // "jwt expired"
}

// Bypass with MAX_SAFE_INTEGER clockTolerance
const payload = jwt.verify(expiredToken, SECRET, {
  clockTolerance: Number.MAX_SAFE_INTEGER  // 9007199254740991
});

console.log(payload); // { sub: "user", role: "admin", ... } — token accepted!

Root Cause

In verify.js, the expiry check is:

if (clockTimestamp >= payload.exp + (options.clockTolerance || 0)) {
  return done(new TokenExpiredError(...));
}

When clockTolerance is Number.MAX_SAFE_INTEGER, the addition payload.exp + 9007199254740991 produces a value far larger than any realistic clockTimestamp. The comparison becomes:

1775002429 >= 9007200998207420  →  false

So the expiry check is skipped entirely. The same issue affects the nbf (not before) check via the same pattern.

No validation is performed on clockTolerance beyond checking it is a number:

// Current validation (insufficient):
if (options.clockTimestamp && typeof options.clockTimestamp !== "number") {
  return done(new JsonWebTokenError("clockTimestamp must be a number"));
}
// clockTolerance has NO validation at all

Impact

Any application that:

  1. Reads clockTolerance from user input, a config file, environment variable, or a database without strict validation, OR
  2. Has a dependency that passes an unvalidated clockTolerance

...is vulnerable to complete expiry bypass. An attacker who can influence the clockTolerance value can reuse tokens that expired days, months, or years ago.

This is particularly dangerous in multi-tenant systems where token verification options may be partially user-controlled.

Suggested Fix

Add an upper bound to clockTolerance. A reasonable maximum is 300 seconds (5 minutes) or at most 86400 (1 day). For example:

if (options.clockTolerance !== undefined) {
  if (typeof options.clockTolerance !== "number" || options.clockTolerance < 0) {
    return done(new JsonWebTokenError("clockTolerance must be a non-negative number"));
  }
  if (options.clockTolerance > 300) {
    return done(new JsonWebTokenError("clockTolerance must not exceed 300 seconds"));
  }
}

Alternatively, document clearly that clockTolerance must be a small value and add a warning when it exceeds a reasonable threshold.


Discovered via manual source code audit of v9.0.3.

Reported by Travis Burmaster — [email protected]

Lingua principale
JavaScript
Stelle
18.2k
Fork
1.3k
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di auth0/node-jsonwebtoken

Tutte le issue di auth0/node-jsonwebtoken

Issue simili

Altre issue su JavaScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.