Skip to content

fix: prevent Content-Length smuggling, log format-string injection, and common-pool starvation#3395

Merged
velo merged 14 commits into
masterfrom
feature/request-body-streaming
Jun 6, 2026
Merged

fix: prevent Content-Length smuggling, log format-string injection, and common-pool starvation#3395
velo merged 14 commits into
masterfrom
feature/request-body-streaming

Conversation

@velo

@velo velo commented Jun 6, 2026

Copy link
Copy Markdown
Member

Summary

Security fixes identified during review of the request-body-streaming refactor:

  • CWE-444 HTTP Request Smuggling (RequestTemplate.java): Restored the defensive Content-Length header clear before conditionally setting it. The streaming refactor had accidentally removed the header(CONTENT_LENGTH, Collections.emptyList()) reset, allowing duplicate or stale Content-Length values when body() is called more than once or when a prior header already existed.
  • CWE-134 Format-String Injection (Logger.java): The body-logging call was changed from log(configKey, "%s", body.toString()) to log(configKey, body.toString()), making raw request body the printf format string. Any % in the body (e.g. JSON {"discount":"50%"}) throws an unchecked IllegalFormatException propagating out of logRequest. Fixed by restoring "%s" as the format argument.
  • ForkJoinPool starvation / DoS (AsyncApacheHttp5Client.java, Http2Client.java): Both async clients defaulted to ForkJoinPool.commonPool() as the executor for the blocking body-write bridge. This pins one JVM-wide common-pool thread per in-flight request, defeating the async model and enabling DoS via pool starvation. Replaced with a dedicated daemon-thread newCachedThreadPool().

Test plan

  • mvn test passes (778 tests — core: 601, hc5: 102, java11: 75, 0 failures)
  • Integration tests via mvn clean install -Pdev
  • Verify no regression in HTTP/1.1 and HTTP/2 clients under concurrent load

🤖 Generated with Claude Code

yvasyliev and others added 14 commits May 18, 2026 07:14
Co-authored-by: trumpetinc <6618744+trumpetinc@users.noreply.github.com>
Co-authored-by: trumpetinc <6618744+trumpetinc@users.noreply.github.com>
Co-authored-by: trumpetinc <6618744+trumpetinc@users.noreply.github.com>
Co-authored-by: trumpetinc <6618744+trumpetinc@users.noreply.github.com>
Co-authored-by: trumpetinc <6618744+trumpetinc@users.noreply.github.com>
Co-authored-by: trumpetinc <6618744+trumpetinc@users.noreply.github.com>
Co-authored-by: trumpetinc <6618744+trumpetinc@users.noreply.github.com>
Co-authored-by: trumpetinc <6618744+trumpetinc@users.noreply.github.com>
Co-authored-by: trumpetinc <6618744+trumpetinc@users.noreply.github.com>
Co-authored-by: trumpetinc <6618744+trumpetinc@users.noreply.github.com>
Co-authored-by: trumpetinc <6618744+trumpetinc@users.noreply.github.com>
…hanges and replacements

Co-authored-by: trumpetinc <6618744+trumpetinc@users.noreply.github.com>
Co-authored-by: trumpetinc <6618744+trumpetinc@users.noreply.github.com>
…nd common-pool starvation in streaming bodies

Signed-off-by: Marvin Froeder <velo.br@gmail.com>
@velo velo enabled auto-merge (squash) June 6, 2026 09:34
@velo velo merged commit f9159cf into master Jun 6, 2026
4 checks passed
@velo velo deleted the feature/request-body-streaming branch June 6, 2026 09:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants