Oct 8, 2026·7 min read·3 visits
A validation flaw in fast-jwt's cache logic allows expired tokens without an iat claim to bypass verification and remain valid for up to 10 minutes.
An authentication bypass vulnerability in NearForm's fast-jwt before version 6.3.4 allows attackers to replay expired tokens due to an error in the verifier's cache expiration logic. When caching is enabled, the cache TTL defaults to 10 minutes instead of honoring the token's exp claim if the token lacks an iat claim.
NearForm fast-jwt is a high-performance JSON Web Token (JWT) library written for Node.js. It implements an in-memory Least Recently Used (LRU) cache to store verified payloads. This caching layer allows the application to bypass cryptographic operations on subsequent requests presenting the same token, significantly reducing CPU overhead.
The vulnerability designated as CVE-2026-107719 exists within this verification caching logic in src/verifier.js. When verification caching is enabled, the library fails to limit the cache entry lifetime to the token's expiration (exp) timestamp if the token payload does not contain an "issued at" (iat) claim. Consequently, the cache retains the token's validity beyond its absolute expiration date, exposing an authentication bypass risk via session replay.
The flaw falls under the CWE-613 classification (Insufficient Session Expiration). Because the verification check relies on a stateful cache lookup prior to checking the cryptographic signature or parsing the actual token payload, an attacker can reuse a previously authenticated token after it has expired. This vulnerability does not allow token forgery, but it significantly extends the window of opportunity for an attacker utilizing intercepted or leaked tokens.
The root cause of CVE-2026-107719 lies in the logical coupling of the exp (Expiration) claim check with the optional iat (Issued At) claim inside the cacheSet helper function in src/verifier.js. According to the JSON Web Token (JWT) specification (RFC 7519), the iat claim is entirely optional. However, many production systems and identity providers construct tokens using only the mandatory payload properties and the exp claim, omitting iat to minimize token size or simplify generation.
When fast-jwt caches a verified token, it attempts to set the cache entry's maximum lifetime based on the token's claims. In vulnerable versions, the calculation of the upper expiration bound is wrapped entirely in a conditional statement that requires the iat claim to be present. If a token without an iat claim is verified, the evaluation of hasIat returns false, causing the system to skip the block that calculates the token's exact absolute expiration time.
Because the code bypasses the evaluation of the exp claim when iat is absent, the cache entry’s maximum timestamp defaults to 0. A downstream fallback mechanism then intercepts this uninitialized value and overwrites it with the default maximum Cache Time-To-Live (TTL), which defaults to 10 minutes. This behavior ensures that the token remains cached as valid, even if the token’s intrinsic lifetime was explicitly configured to expire in a much shorter interval.
To understand the vulnerability, let us analyze the code path in src/verifier.js before the patch was applied. The cacheSet function is responsible for determining the lower bound (minTime) and upper bound (maxTime) of a token's cached lifetime.
// Vulnerable implementation in src/verifier.js
const hasIat = payload && typeof payload.iat === 'number'
// Add time range of the token
if (hasIat) {
cacheValue[1] = !ignoreNotBefore && typeof payload.nbf === 'number' ? payload.nbf * 1000 - clockTolerance : 0
if (!ignoreExpiration) {
if (typeof payload.exp === 'number') {
cacheValue[2] = payload.exp * 1000 + clockTolerance
} else if (maxAge) {
cacheValue[2] = payload.iat * 1000 + maxAge + clockTolerance
}
}
}In the code above, if payload.iat is absent, the entire conditional block is skipped. The array element cacheValue[2], which represents the absolute expiration time of the cached entry, remains 0. The function later checks if cacheValue[2] === 0 and, if so, re-assigns it to the default maxTTL limit, exposing the security gap.
The patch introduced in commit fc1ddbbe5ce38066ba2cea0b0ce0233932757167 completely decouples the evaluation of the nbf and exp claims from the presence of the iat claim. The refactored code calculates these bounds independently.
// Patched implementation in src/verifier.js
cacheValue[1] = !ignoreNotBefore && typeof payload.nbf === 'number' ? payload.nbf * 1000 - clockTolerance : 0
let expiresAt = clockTimestamp + clockTolerance + cacheTTL
if (!ignoreExpiration && typeof payload.exp === 'number') {
// Select the earlier of the cache TTL limit and token expiration limit
expiresAt = Math.min(expiresAt, payload.exp * 1000 + clockTolerance)
}
// As in its validator, maxAge counts from iat and ignores clockTolerance
if (typeof maxAge === 'number' && typeof payload.iat === 'number') {
expiresAt = Math.min(expiresAt, payload.iat * 1000 + maxAge)
}
cacheValue[2] = expiresAtIn the patched code, expiresAt is first initialized to the safest maximum default. If the token contains an exp claim, the code uses Math.min to force the cache expiration to honor the earlier of the cache's standard TTL or the token's cryptographic expiration time. This effectively eliminates the coupling bug and guarantees that short-lived tokens expire from the cache when they are supposed to.
Exploitation of CVE-2026-107719 requires specific prerequisites. An attacker must first obtain a valid, signed JSON Web Token issued by the target application. This token must lack the iat claim and must be actively verified by the server once to populate the LRU cache. Additionally, the exploit attempt must occur after the token's formal expiration time but before the application's configured cache TTL has elapsed.
An attacker with network access to the API endpoints can intercept their own low-privilege token or steal a token via browser-based vectors. Once the token expires, the attacker replays the expired JWT in successive HTTP requests. Because the server uses fast-jwt with caching enabled, the verifier intercepts the request, locates the token in the cache, and matches the query against the cached entry.
Due to the logical error in the unpatched cacheSet function, the cached entry remains valid. The application bypasses signature and formal temporal validation, treating the request as authenticated. This extends the active session window of the expired token up to the default cache TTL, which is typically 10 minutes, allowing unauthorized action execution.
The impact of this vulnerability is assessed with a CVSS 3.1 base score of 4.2 (Medium severity). While the vulnerability allows authentication bypass, the threat vector is constrained because the attacker cannot forge arbitrary tokens. The attacker is limited to replaying authentic, previously signed tokens that have been validated by the host application at least once during the current cache cycle.
Furthermore, the exploitation window is restricted to the difference between the token's intended lifetime and the configured cache TTL. If an application utilizes short-lived tokens (such as 30-second single-use tokens) to secure sensitive endpoints, this vulnerability increases the risk window tenfold. Within this window, the attacker maintains authorized privileges, potentially accessing confidential data or performing state-modifying actions.
This issue is particularly critical in microservices architectures where token validation occurs frequently at API gateways. Since gateways rely heavily on caching to maintain low latencies, a high percentage of incoming requests are subject to cache validation. This architecture amplifies the vulnerability’s impact, making immediate patching of the verifier layer a priority.
The primary remediation strategy is upgrading fast-jwt to version 6.3.4 or higher, which completely resolves the cache expiration calculation bug. For environments where package upgrades require prolonged QA testing, immediate tactical workarounds can be applied to eliminate the vulnerability.
The most effective workaround is disabling the verifier cache by passing cache: false or omitting the cache configuration option within the createVerifier function call. This forces the library to perform complete signature and claim validation for every request, removing the vulnerable cache lookup path entirely.
Alternatively, if caching must be preserved to maintain API performance, developers can configure the token signers to explicitly include the iat claim in all outbound tokens. Ensure that the noTimestamp configuration option is set to false when using fast-jwt's createSigner. Security teams should also verify that upstream identity providers are configured to append the iat claim to all minted tokens.
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
fast-jwt NearForm | < 6.3.4 | 6.3.4 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-613: Insufficient Session Expiration |
| Attack Vector | Network (Remote) |
| CVSS Score | 4.2 (Medium) |
| Exploit Status | poc |
| KEV Status | Not Listed |
| Affected Component | src/verifier.js (cacheSet function) |
The application does not invalidate a session or token after a pre-determined period of inactivity or absolute expiration, allowing an attacker to reuse expired session credentials.
CVE-2026-61427 is a critical authentication bypass and improper input validation vulnerability within the Model Context Protocol (MCP) HTTP-stream server of PraisonAI. In versions prior to 4.6.78, the server lacks authentication by default and forwards client messages directly to Python tool handlers without input validation. When bound to non-localhost interfaces, this permits unauthenticated remote attackers to perform unauthorized administrative operations and execute tools.
CVE-2026-107387 is a high-impact uncontrolled memory allocation vulnerability in music-metadata, a widely used Node.js metadata parser. The flaw occurs in the APEv2 tag parser, where the library reads an attacker-controlled 32-bit integer indicating the tag size and immediately requests a corresponding heap buffer reservation. Because this allocation occurs before validating if the input stream actually contains those bytes, an attacker can supply a minuscule audio file to trigger large, disproportionate allocations, resulting in heap exhaustion and an uncatchable process-wide Out of Memory (OOM) crash.
An input validation vulnerability exists in music-metadata versions prior to 11.16.0, where parsing a crafted MP4 file containing a sample-description (stsd) box with a zero-value size entry causes a synchronous infinite loop and memory exhaustion, resulting in complete Denial of Service.
A path traversal vulnerability in datamodel-code-generator allows remote attackers to write or overwrite arbitrary files on the local host filesystem via a manipulated Protobuf schema containing malicious weak import paths.
PraisonAI is vulnerable to an arbitrary local file read vulnerability prior to version 4.6.78. The flaw is in the ContextGatherer component, where validation checks are executed only after files are parsed and appended to the context bundle, bypassing security constraints.
An algorithmic complexity vulnerability (CWE-770) in the Excelize library allows remote attackers to cause resource exhaustion (100% CPU usage) via a crafted Microsoft Excel spreadsheet. This occurs because the look-ahead row index parsing in Rows.Columns() fails to enforce upper boundary limits, enabling an out-of-bounds row index to trigger an infinite seek loop inside the Rows iterator.