Prevent header-controlled input from reaching raw HTTP response headers or request lines. Validate and encode CR and LF characters, use framework-safe response APIs, and reject malformed header values. Security testing should confirm that caches, proxies, and downstream clients do not interpret attacker-supplied data as a separate message.
How to stop CR and LF from turning one message into two
Request/response splitting happens when attacker-controlled content reaches a raw HTTP header or start line without strict validation. The practical fix is to treat carriage return and line feed as dangerous control characters, not ordinary text, and to ensure application code never concatenates untrusted values into protocol framing.
Use framework-safe header and response APIs that canonicalise or reject invalid values before they are written to the wire. That matters because once an application writes raw header bytes, downstream components can interpret a single response as two messages, or split one request into multiple requests.
For pages, redirects, file downloads, and dynamic content-disposition values, the safest pattern is to use vetted library helpers rather than manual string assembly. When the application must echo user input, encode it for the specific output context and reject any value that contains embedded CR, LF, or header delimiters.
Where validation and output handling need to be strictest
The highest-risk sinks are anything that influences HTTP request/response splitting and related web application attack patterns, especially redirects, reflected header values, proxy-aware applications, and systems that build headers from query parameters, cookies, filenames, or upstream metadata. These are the places where a malformed value can become a protocol boundary problem instead of a simple input bug.
Validation should be fail-closed. If a value is meant for a header field, restrict it to the narrow character set that header field actually needs. If a value is meant for a request path, query string, or body, keep it in that context and never repurpose it as header material later in the response flow.
Downstream infrastructure also matters. Proxies, reverse proxies, CDNs, load balancers, and browser caches can all amplify the impact if they disagree about where one message ends and the next begins. A response that looks harmless in the application layer can still become dangerous when a front-end and back-end parse it differently.
What to verify before you treat the issue as fixed
Test the application with payloads that include encoded and raw CR/LF variants, then confirm that the framework rejects them consistently at every layer that handles headers or request lines. Verification should include the full path through application code, reverse proxy, cache, and client-facing edge, because the bug is only gone if every component sees one unambiguous message.
Also confirm that security tests cover both direct injection and transformation paths. Input sanitisation can be bypassed if data is decoded twice, normalized differently by separate components, or copied from one trusted field into another unsafe context later in the request lifecycle.
A useful complement is to review the response patterns that follow redirects, errors, and partial failures. These are common places where developers manually write headers or reuse helper code that was never designed to handle untrusted values.
Risk and Threat Considerations
Request/response splitting can lead to cache poisoning, header injection, response smuggling, and cross-user content confusion. Even when the initial payload looks small, the effect can spread because shared infrastructure may store or replay a tainted response for other users.
Failure mechanism: The application places attacker-controlled bytes into an HTTP header or status line, and a downstream component parses CR/LF as a message boundary instead of data. That lets the attacker create an extra response, modify headers, or desynchronise front-end and back-end parsing.
Impact: The result can be session exposure, cache poisoning, security control bypass, user redirection, or injection into another user’s browser session. In distributed web stacks, the operational blast radius is often larger than the original input bug suggests.
Framework Alignment
Standards & Framework Alignment
This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.
OWASP ASVS, NIST SP 800-53 Rev 5 and CIS Controls v8 set the governance and control requirements practitioners need to meet.
| Framework | Control / Reference | Relevance |
|---|---|---|
| OWASP ASVS | V12 — Secure Communication | Covers safe handling of HTTP transport and message boundaries. |
| V16 — Security Logging and Error Handling | Error and redirect handling often becomes the injection sink for splitting bugs. | |
| Recommendation — Use safe transport and output APIs that prevent message-boundary injection. Ensure error and redirect handlers do not serialize attacker-controlled header data. | ||
| NIST SP 800-53 Rev 5 | SI-10 — Information Input Validation | CR/LF filtering is an input-validation control for unsafe HTTP header data. |
| SC-23 — Session Authenticity | Request/response splitting can corrupt session-related traffic and shared responses. | |
| Recommendation — Validate and reject header-controlled input before it reaches protocol framing. Protect session-related responses from injection and boundary confusion. | ||
| CIS Controls v8 | CIS-16 — Application Software Security | Application-layer output handling is the main place splitting flaws are fixed. |
| Recommendation — Harden application output paths that build HTTP headers or request lines. | ||
Practitioner Guidance
What to prioritise: Remove every code path that writes raw, user-influenced bytes into response headers first, then review request-building logic that forwards user data into upstream HTTP clients or gateway calls. Those two paths are the most likely to create exploitable message-boundary confusion.
What to verify: Make sure framework helpers, proxy settings, and custom middleware all reject header delimiters the same way. If one layer sanitises and another reserialises, the application can appear safe while the transport layer still becomes ambiguous.
Practitioner takeaway: The control objective is not just input sanitisation, it is preserving a single, unambiguous HTTP message boundary from application code to the last intermediary.
Related resources from NHI Mgmt Group
- How should security teams reduce the risk of HTTP request desynchronisation in shared proxy architectures?
- How should security teams reduce request smuggling risk when HTTP/2 is deployed through front-end downgrading layers?
- How should security teams reduce HTTP request smuggling risk in multi-tier web architectures?
- Why does HTTP request splitting create such serious risk for backend services and other users?