You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: recognise RegExp matchers created in another realm
The allowed* verifier options gated their RegExp handling on
`r instanceof RegExp`, which is a prototype-chain identity check rather
than a type check. A RegExp built in a different JavaScript realm, for
example via `vm.runInNewContext`, fails it despite being a fully
functional RegExp with a live lastIndex.
Such a matcher fell through to the duck-typed `test()` branch and was
stored raw, so a cross-realm /g or /y pattern reintroduced the
non-determinism the lastIndex reset (CVE-2026-35040) fixed: a valid
token alternated between accepted and rejected across successive calls.
The same gap silently skipped the FAST_JWT_UNSAFE_REGEXP ReDoS warning
for a cross-realm pattern.
Both call sites now share an `isRegExpLike()` helper. `isRegExp` from
node:util inspects the engine's internal slot, so it is realm
independent; the `instanceof` arm is kept so objects presenting as
RegExps without the internal slot keep the handling they had before.
`Object.prototype.toString.call()` was avoided because its brand can be
forged through Symbol.toStringTag.
Widening the predicate brings real cross-realm RegExps into the reset
path for the first time, where an unconditional `lastIndex` write throws
for a frozen matcher. The write is now wrapped so an unwritable matcher
falls through to test() instead, which also fixes frozen same-realm
RegExps that threw on every call before.
A Proxy over a cross-realm /g RegExp remains non-deterministic: it
satisfies neither isRegExp nor instanceof RegExp, so it is treated as a
custom matcher. That is pre-existing behaviour and out of scope here.
Closes#654
Copy file name to clipboardExpand all lines: README.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -164,6 +164,8 @@ Create a verifier function by calling `createVerifier` and providing one or more
164
164
165
165
- `allowedNonce`: A string, a regular expression, an array of strings or an array of regular expressions containing allowed values for the nonce claim (`nonce`). By default, all values are accepted.
166
166
167
+
For the five `allowed*` options above, any object exposing a `test(value)` method happens to work at runtime in plain JavaScript, but it is not part of the TypeScript types and is not a supported configuration. fast-jwt resets a `RegExp` matcher's `lastIndex` before each test, so a stateful pattern validates deterministically, but it performs no state management on a custom matcher's behalf, so a stateful custom matcher is the caller's responsibility.
168
+
167
169
- `requiredClaims`: An array of strings containing which claims should exist in the token. By default, no claim is marked as required.
168
170
169
171
- `ignoreExpiration`: Do not validate the expiration of the token. Default is `false`.
0 commit comments