Skip to content

🛡️ Sentinel: [HIGH] Fix DoS vulnerability in request sanitization#6300

Draft
EffortlessSteven wants to merge 1 commit into
mainfrom
sentinel/fix-dos-chunked-transfer-encoding-9885799808337788363
Draft

🛡️ Sentinel: [HIGH] Fix DoS vulnerability in request sanitization#6300
EffortlessSteven wants to merge 1 commit into
mainfrom
sentinel/fix-dos-chunked-transfer-encoding-9885799808337788363

Conversation

@EffortlessSteven

Copy link
Copy Markdown
Member

🚨 Severity: HIGH
💡 Vulnerability: The request sanitization middleware relied on the content-length header to limit payload sizes but failed to handle requests with transfer-encoding: chunked missing a content length, leaving the server vulnerable to unbounded payload DoS attacks.
🎯 Impact: Attackers could send unbounded chunked payloads to exhaust server resources (memory/CPU) and cause a Denial of Service.
🔧 Fix: Explicitly reject requests with transfer-encoding: chunked if they lack a defined content length in the request_sanitization_middleware.
✅ Verification: Ran unit tests and validated that the application correctly returns 411 Length Required for such requests.


PR created automatically by Jules for task 9885799808337788363 started by @EffortlessSteven

The request sanitization middleware relied solely on the `content-length`
header to limit payload sizes. This left the server vulnerable to unbounded
payload DoS attacks if a request used `transfer-encoding: chunked` without
a defined content length.

This commit explicitly rejects requests that specify `transfer-encoding: chunked`
if they lack a `content-length` header.
@google-labs-jules

Copy link
Copy Markdown

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 52fad141-5fba-4bdc-bb35-0ac6e1733fab

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sentinel/fix-dos-chunked-transfer-encoding-9885799808337788363

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a security check to prevent unbounded payload DoS attacks by rejecting chunked transfer encoding requests that lack a content-length header, and documents this in .jules/sentinel.md. However, feedback points out that according to RFC 9112, standard-compliant chunked requests must not contain a Content-Length header, meaning the current implementation would reject all valid chunked requests. It is recommended to either reject all chunked requests outright or enforce a maximum body size limit on the request stream itself.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +497 to +504
if !request.headers().contains_key("content-length")
&& let Some(te) = request.headers().get("transfer-encoding")
&& let Ok(te_str) = te.to_str()
&& te_str.to_lowercase().contains("chunked")
{
warn!("Rejected chunked request without content-length");
return Err(StatusCode::LENGTH_REQUIRED);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

According to the HTTP/1.1 specification (RFC 9112, Section 6.2), a sender must not send a Content-Length header in any message that contains a Transfer-Encoding header.

By rejecting chunked requests that lack a Content-Length header, this middleware will reject all standard-compliant chunked requests, effectively breaking chunked transfer encoding support entirely.

If the goal is to prevent unbounded payloads:

  1. If chunked transfer encoding is not supported/allowed: Reject all chunked requests outright, regardless of the presence of a Content-Length header.
  2. If chunked transfer encoding is supported: Enforce a maximum body size limit on the request stream itself (e.g., using tower_http::limit::RequestBodyLimitLayer or Axum's DefaultBodyLimit), rather than relying on headers which can be omitted or spoofed.

If you wish to reject all chunked requests to prevent DoS, you should remove the content-length check.

    if let Some(te) = request.headers().get("transfer-encoding")
        && let Ok(te_str) = te.to_str()
        && te_str.to_lowercase().contains("chunked")
    {
        warn!("Rejected chunked request: chunked transfer encoding is not supported");
        return Err(StatusCode::BAD_REQUEST);
    }

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request documents a vulnerability regarding unbounded payload DoS via chunked transfer encoding and implements a mitigation in the request sanitization middleware by rejecting chunked requests that lack a content-length header. Feedback points out that requiring content-length alongside transfer-encoding: chunked violates the HTTP/1.1 specification and introduces HTTP Request Smuggling risks. It is recommended to either reject all chunked requests outright or enforce a limit on the request body stream itself.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +497 to +504
if !request.headers().contains_key("content-length")
&& let Some(te) = request.headers().get("transfer-encoding")
&& let Ok(te_str) = te.to_str()
&& te_str.to_lowercase().contains("chunked")
{
warn!("Rejected chunked request without content-length");
return Err(StatusCode::LENGTH_REQUIRED);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Requiring a content-length header for requests with transfer-encoding: chunked violates the HTTP/1.1 specification (RFC 9112, Section 6.2), which states that a sender MUST NOT send a Content-Length header if Transfer-Encoding is present. Standard-compliant clients sending chunked requests will be broken by this change.

Additionally, allowing chunked requests only when content-length is present introduces a risk of HTTP Request Smuggling, as different proxies/servers handle the conflict between these two headers differently.

Recommended Approaches:

  1. If chunked requests are not supported: Reject all chunked requests outright without checking for content-length.
  2. If chunked requests are supported: Enforce a limit on the request body stream itself (e.g., using Axum's DefaultBodyLimit or wrapping the body in a size-limiting stream like http_body_util::Limited) rather than relying on header validation in this middleware.
    if let Some(te) = request.headers().get("transfer-encoding")
        && let Ok(te_str) = te.to_str()
        && te_str.to_lowercase().contains("chunked")
    {
        warn!("Rejected chunked request to prevent unbounded payload DoS");
        return Err(StatusCode::BAD_REQUEST);
    }

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.

1 participant