Sep 15, 2026·6 min read·5 visits
An inverted logic comparison in http4s DigestAuth middleware prevents the eviction of stale cryptographic nonces while deleting fresh ones. Unauthenticated attackers can repeatedly request authentication challenges, filling the JVM heap memory until the application crashes.
A critical memory leak vulnerability exists in the server-side DigestAuth middleware of the http4s library. Due to a logical inversion in the stale-nonce clean-up routine, the internal cache fails to evict stale nonces while prematurely purging fresh ones. Unauthenticated remote attackers can exploit this behavior by repeatedly prompting the server for authentication challenges, leading to unbounded memory consumption and application crashes via a java.lang.OutOfMemoryError.
The vulnerability affects the http4s Scala library, specifically within its server-side DigestAuth middleware implemented in components such as DigestAuth.scala, NonceKeeper.scala, and NonceKeeperF.scala. The DigestAuth middleware provides HTTP Digest Access Authentication, protecting defined routes by validating request credentials against unique, short-lived cryptographic tokens called nonces.
To prevent reply attacks and control session validity, the server maintains nonces inside an internal, insertion-ordered LinkedHashMap. The middleware uses this map to keep track of valid tokens and is designed to periodically evict expired tokens that exceed a configured lifetime (staleTimeout). Under normal operations, this cache management system ensures that memory consumption remains bounded and stable even under heavy user activity.
However, a logic error in the eviction subroutine reverses the stale-nonce check condition. The application incorrectly retains expired nonces indefinitely and deletes active sessions instead. Because this middleware operates on unauthenticated endpoints to challenge incoming requests, any remote user can trigger the generation of new cached nonces, presenting a major remote attack surface.
The root cause of this vulnerability lies in a logic inversion bug within the eviction routing of both the legacy NonceKeeper class and the effect-based NonceKeeperF class. Under the HTTP Digest Authentication specification, nonces are tracked chronologically to ensure older elements are processed first. The eviction loop utilizes an iterator over the underlying map, walking from the oldest entry to the newest.
In the vulnerable codebase, the age of each nonce is evaluated against the staleTimeout parameter using the following comparison: staleTimeout > age (calculated as current time minus creation time). When this inequality evaluates to true, the elapsed time is less than the threshold, indicating that the token is still active and valid. Because of the logic flaw, the code incorrectly identifies active nonces as candidates for deletion and removes them via it.remove().
Conversely, when the loop encounters the first truly expired nonce, the age exceeds the timeout, making the statement staleTimeout > age evaluate to false. At this point, the conditional check fails and the recursive eviction subroutine halts immediately. Since the collection is organized sequentially by insertion time, the presence of a single expired nonce at the head of the collection blocks all subsequent stale nonces from being evaluated, leading to a permanent memory leak.
Analyzing the implementation details highlights the exact line-level differences before and after the remediation. In the vulnerable version of NonceKeeper.scala, the tail-recursive clean-up loop was written as follows:
val it = nonces.values().iterator()
@tailrec
def dropStale(): Unit = {
// BUG: staleTimeout > age evaluates to true only for active, fresh nonces
if (it.hasNext && staleTimeout > d - it.next().created.getTime) {
it.remove() // Incorrectly deletes the valid nonce
dropStale() // Recursively continues
}
// Loop exits on the first expired nonce, leaving it and all newer entries in memory
}In the patched version of the file, the maintainers corrected the conditional operator to verify that the elapsed age is greater than or equal to the timeout threshold:
val it = nonces.values().iterator()
@tailrec
def dropStale(): Unit = {
// FIX: Verify that the nonce has actually aged past the stale timeout limit
if (it.hasNext && d - it.next().created.getTime >= staleTimeout) {
it.remove() // Safely expels the expired nonce
dropStale() // Continues to clean up subsequent expired nonces
}
// Loop correctly terminates once it encounters the first valid (fresh) nonce
}Additionally, to safeguard the application from extreme, rapid volume surges that could overwhelm the background thread's clean-up frequency, the maintainers implemented a hard cap on the size of the underlying LinkedHashMap by overriding the removeEldestEntry method in NonceKeeperF.scala. This ensures that the map self-truncates if it reaches the maximum capacity defined by the maxNonces parameter.
Exploiting this flaw does not require authentication or specific request structures. An attacker targets any endpoint protected by the DigestAuth middleware and executes the following programmatic steps:
The attacker issues an initial HTTP request to the protected path without an Authorization header.
The server responds with an HTTP 401 Unauthorized status and includes a WWW-Authenticate header containing a newly generated, unique nonce value.
The server allocates memory for this new nonce and stores it in the LinkedHashMap cache.
The attacker ignores the challenge and repeats step 1 at a high frequency. Because the eviction subroutine is broken, none of the generated nonces are ever discarded from the server's memory.
This sequence can be automated with simple HTTP flooding utilities. Over time, the accumulated footprint of the NonceF metadata blocks, hash map entries, and string keys exhausts the allocated Java Virtual Machine (JVM) heap space, resulting in severe performance degradation and an eventual crash.
The primary impact of CVE-2026-69208 is complete denial of service. Because the application crashes due to a heap exhaustion event (java.lang.OutOfMemoryError), the entire service becomes unresponsive, affecting all other endpoints running on the same JVM instance.
While the patch remediates the logic inversion and introduces a hard size limit (maxNonces), security teams must evaluate potential residual risks. The default value for maxNonces is set to 1,000,000. In resource-constrained environments (such as Kubernetes pods running with less than 1GB of RAM), storing up to one million complex nonce objects, dates, and corresponding reference metadata inside the JVM heap may still consume sufficient memory to trigger an OutOfMemoryError before the threshold limit is reached.
Furthermore, legacy methods retained for binary compatibility preserve the old signatures, which default the maxNonces parameter to Int.MaxValue. If downstream applications call these deprecated interfaces directly, they will remain unbounded, relying exclusively on the temporal clean-up loop.
To fully resolve the vulnerability, organizations should upgrade their http4s dependencies to the patched releases.
Applications tracking the 0.23.x release branch must be updated to version 0.23.35 or later. Applications tracking the 1.0.0 milestone branch must be upgraded to 1.0.0-M47 or later.
If upgrading is not immediately possible, security teams can implement several tactical mitigations:
Configure upstream Web Application Firewalls (WAF) or reverse proxies to rate-limit unauthenticated requests targeting protected routes, preventing rapid nonce generation.
Set up explicit alerts on JVM memory usage, tracking rapid growth of NonceF and LinkedHashMap object allocations.
Avoid calling deprecated middleware builders that default the maximum nonce count to Int.MaxValue, and instead transition to initialization patterns that allow setting a conservative custom limit for maximum cached nonces.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
http4s http4s | < 0.23.35 | 0.23.35 |
http4s http4s | >= 1.0.0-M1, < 1.0.0-M47 | 1.0.0-M47 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-400 / CWE-401 |
| Attack Vector | Network |
| CVSS v3.1 Score | 7.5 (High) |
| Attack Complexity | Low |
| Privileges Required | None (Unauthenticated) |
| Impact | Denial of Service (JVM Heap Exhaustion) |
| Exploit Status | PoC (Proof of Concept) available in test suites |
| CISA KEV Status | Not Listed |
The software does not control, or limits improperly, the allocation and maintenance of a limited resource, enabling an actor to influence the amount of resources consumed.
A constellation of five distinct security flaws (F1 through F5) in `@zereight/mcp-gitlab` prior to version 2.1.30 allows unauthenticated remote access, read-only policy bypasses, DNS rebinding, and denial-of-service via session exhaustion.
A critical security vulnerability has been identified in the @zereight/mcp-gitlab implementation of the Model Context Protocol (MCP) server. Prior to version 2.1.30, the server lacks HTTP Host and Origin header validation on its Streamable HTTP transport interface (/mcp). This security omission permits remote attackers to bypass the Same-Origin Policy (SOP) via a DNS Rebinding attack. Under this vector, an attacker can route malicious API requests to the victim's local or internal MCP server, thereby gaining unauthorized control over the victim's GitLab account and resources.
A critical Server-Side Request Forgery (SSRF) vulnerability in @zereight/mcp-gitlab allows attackers to leak sensitive GitLab Private-Tokens by supplying an arbitrary external hostname via the X-GitLab-API-URL header when dynamic routing is enabled.
An incomplete security fix in Shopper prior to version 2.9.2 exposes a Broken Function Level Authorization (BFLA) vulnerability in the Media component. Low-privileged administrative users with 'browse_products' permissions can bypass role-based access control policies to execute the 'store' action and modify product media.
A critical authorization bypass and insecure direct object reference (IDOR) vulnerability was discovered in Shopper, a Headless e-commerce Admin Panel. Due to missing authorization chains on table actions and the lack of a locked property on the collection state model, authenticated low-privilege staff can detach products from arbitrary collections.
CVE-2026-59973 is a high-severity Server-Side Request Forgery (SSRF) vulnerability in FrontMCP and its underlying OpenAPI parsing library, mcp-from-openapi. The flaw allows authenticated attackers capable of importing or configuring OpenAPI specifications to bypass string-based hostname filtering mechanisms. By employing DNS wildcard loopbacks, HTTP redirects, or IPv4-mapped IPv6 address formatting, attackers can coerce the application into sending HTTP requests to internal networks, loopback adapters, and cloud metadata environments.