Response splitting happens when an application copies untrusted input into a response header without removing carriage return and line feed characters. The attacker's input then ends the header section early, and one response looks like two. The reliable fix is to stop anything but your protocol library from writing those characters.
How the RFC describes it
RFC 9112 section 11.1 calls response splitting a common technique that uses CRLF injection. An attacker inserts encoded CR and LF characters that the application echoes into header fields, for example the Location header of a redirect. The application's single response then appears to be two, and the attacker controls the second.
Why that matters: a cache, proxy or browser that reads the stream as two responses can store or show attacker content for a URL the user trusts.
A typical vulnerable pattern
// Unsafe: next comes straight from the query string
res.setHeader("Location", req.query.next);
res.statusCode = 302;
res.end();
If next can carry encoded CR and LF bytes that get decoded before the header is written, the attacker injects extra headers or a second response. Modern runtimes often reject such values, but older stacks, custom servers and some proxies do not.
Why filtering is the weak defense
The RFC notes that filtering for strings like %0D and %0A is not reliable, because the application may decode or transform data in other ways before it reaches the header. A blocklist covers the encodings you thought of.
The stronger defense
The RFC phrases the better approach as preventing anything other than the server's core protocol libraries from sending a CR or LF within the header section. In practice:
- Set headers only through the framework API, never by concatenating raw header text.
- Make the framework reject any header value containing CR or LF, and fail closed.
- Validate redirect targets against an allow list of paths or hosts, which also stops open redirects. See safe patterns for login return URLs.
- Keep your HTTP server and libraries updated, since parser fixes land there.
- Log and alert on header write errors, which can be the first sign of probing.
Related parsing rules
The RFC adds that lenient status line parsing and obsolete line folding can also enable splitting. Strict parsers on every hop reduce the chance two components disagree. The same disagreement idea underlies request smuggling.
Review checklist
- Search the code for places that set Location, Set-Cookie or custom headers from request data.
- Confirm tests include values with encoded line breaks.
- Check that any CDN or proxy in front also rejects them.
Where Safeguard fits
Safeguard does not inspect your live traffic. It scans the dependencies and SBOMs behind your web stack for known vulnerabilities and can gate pull requests with policies. Try the free scan at gold.safeguard.sh/scan.
Quick check
Is blocking the strings %0D and %0A enough?
No. The RFC says it is unreliable, because the application may decode or transform the data in other ways.
Which header is a classic injection point?
The Location header of a redirect, which the RFC uses as its example.
Sources
Last reviewed: 19 October 2026.