CVE-2026-69211 Overview
Http4s is a Scala interface for HTTP services. A header injection vulnerability [CWE-113] affects the ResponseCookie.render function in versions prior to 0.23.35 and 1.0.0-M47. The function writes attacker-influenced name, content, domain, path, and extension values without neutralizing semicolons or control characters. Applications that construct a ResponseCookie from unvalidated input can emit injected cookie attributes such as Domain, Path, or SameSite. This widens cookie scope or weakens protections, and embedded control characters may enable HTTP header splitting on permissive backends.
Critical Impact
Attackers who influence cookie field values can inject arbitrary cookie attributes, expand cookie scope, weaken SameSite protections, and trigger HTTP response splitting on permissive HTTP backends.
Affected Products
- Http4s versions prior to 0.23.35
- Http4s 1.0.0 milestone releases prior to 1.0.0-M47
- Scala applications using org.http4s.ResponseCookie with untrusted input
Discovery Timeline
- 2026-09-15 - CVE-2026-69211 published to NVD
- 2026-09-16 - Last updated in NVD database
Technical Details for CVE-2026-69211
Vulnerability Analysis
The defect lives in core/shared/src/main/scala/org/http4s/ResponseCookie.scala. When http4s serializes a ResponseCookie into a Set-Cookie header, it concatenates the name, content, domain, path, and extension fields directly into the output. The renderer does not strip semicolons (;) or control characters such as CR (\r) and LF (\n) from these fields.
Because semicolons delimit cookie attributes, an attacker-controlled value can terminate the current attribute and inject new ones. Injected Domain=, Path=, or SameSite=None directives widen cookie scope across subdomains or downgrade cross-site protections. Injected CR/LF sequences can additionally break the header boundary on permissive HTTP backends, enabling HTTP response splitting.
Root Cause
The ResponseCookie renderer trusted its own case-class fields as safe rather than as attacker-influenced data. The prior documentation even placed sanitization responsibility on the caller. Applications routinely construct ResponseCookie instances from request parameters, form input, or database values, so the assumption of caller-side sanitization was unsafe in practice.
Attack Vector
Exploitation requires an application that builds a ResponseCookie from untrusted input, then returns it in a response. An attacker submits a payload containing a semicolon followed by a chosen attribute, for example value; Domain=.victim.tld; Path=/. The rendered Set-Cookie header is accepted by the browser with the injected scope. Where CR/LF is preserved by the backend, the payload can inject entirely new headers or a full second response.
// Patch excerpt: core/shared/src/main/scala/org/http4s/ResponseCookie.scala
import java.time.ZoneOffset
import java.time.ZonedDateTime
-/** @param extension The extension attributes of the cookie. If there is more
+/** Representation of a cookie as sent as the value of a `Set-Cookie` field.
+ *
+ * @param extension The extension attributes of the cookie. If there is more
* than one, they are joined by semi-colon, which must not appear in an
- * attribute value.
+ * attribute value. It is the caller's responsibility to sanitize illegal
+ * semi-colons from untrusted values.
*/
final case class ResponseCookie(
name: String,
Source: http4s commit 5c8e69a. The patch strips control characters from all five fields and strips semicolons from name, content, domain, and path while preserving the extension delimiter behavior.
Detection Methods for CVE-2026-69211
Indicators of Compromise
- Set-Cookie response headers containing multiple Domain=, Path=, or SameSite= directives for the same cookie.
- Raw CR (\r) or LF (\n) bytes observed within outbound Set-Cookie header values.
- Cookies scoped to a broader domain or path than the application's routing logic should permit.
- Application logs showing user-controlled data (query, form, JSON) flowing into ResponseCookie(...) constructors.
Detection Strategies
- Perform dependency scanning of Scala project build files (build.sbt, project/*.scala) for org.http4s artifacts below 0.23.35 or 1.0.0-M47.
- Add static analysis rules that flag calls to ResponseCookie.apply where any field originates from HTTP request data without validation.
- Fuzz cookie-producing endpoints with payloads containing ;, \r, and \n and inspect emitted headers.
Monitoring Recommendations
- Log full Set-Cookie header values at an upstream reverse proxy and alert on cookies containing more than one attribute of the same type.
- Enable web application firewall (WAF) rules that reject outbound responses containing CR/LF within header values.
- Track deployments of http4s dependencies through the software bill of materials (SBOM) to identify unpatched services.
How to Mitigate CVE-2026-69211
Immediate Actions Required
- Upgrade http4s to 0.23.35 (stable branch) or 1.0.0-M47 (milestone branch).
- Audit all code paths that construct ResponseCookie from request-derived values.
- Rotate any session or authentication cookies that may have been issued with attacker-controlled attributes.
Patch Information
The fix is delivered in http4s v0.23.35 and http4s v1.0.0-M47. Full details are published in GitHub Security Advisory GHSA-7qh7-rghh-698h. The patched ResponseCookie.render strips control characters from name, content, domain, path, and extension, and strips semicolons from the first four fields.
Workarounds
- Validate and reject any cookie field values containing ;, \r, \n, or characters outside the RFC 6265 token/octet sets before constructing ResponseCookie.
- Encode or hash user-controlled data (for example base64url) before placing it into cookie name or content fields.
- Terminate connections at a reverse proxy that rejects malformed Set-Cookie headers until the http4s upgrade is deployed.
# sbt dependency upgrade example
# In build.sbt, pin http4s to the patched version:
libraryDependencies ++= Seq(
"org.http4s" %% "http4s-core" % "0.23.35",
"org.http4s" %% "http4s-server" % "0.23.35",
"org.http4s" %% "http4s-dsl" % "0.23.35"
)
# Then refresh and verify:
sbt update
sbt "show dependencyTree" | grep http4s
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.