CRLF Injection and HTTP Response Splitting
CRLF injection abuses the carriage-return and line-feed characters (\r\n) that HTTP uses to
separate headers. When an application writes unvalidated user input into a response header, an
attacker can inject those characters to forge additional headers — or an entire response body — a
technique known as HTTP response splitting. It is header injection with the same root cause as all
injection: control characters in untrusted data.
How does it work?#
HTTP headers are separated by \r\n, and a blank line (\r\n\r\n) ends the header block. If user
input flows into a header unfiltered:
Set-Cookie: lang=<user_input>
Input: en%0d%0aSet-Cookie:%20admin=true
Result: Set-Cookie: lang=en
Set-Cookie: admin=true ← attacker-forged header
Extend the injection past a blank line and the attacker controls the response body itself, enabling reflected XSS, redirects, or cache poisoning.
What can it lead to?#
| Injected content | Impact |
|---|---|
Extra Set-Cookie | Session fixation, forced values |
Location header | Open redirect |
| Full response body | Reflected XSS, defacement |
| Cache-relevant headers | Cache poisoning |
How do you prevent CRLF injection?#
- Strip or reject
\rand\nin any value placed into a header. - Use framework header APIs, which typically reject control characters for you.
- Never build raw HTTP responses by hand from user input.
CRLF injection is header-layer injection, closely related to request smuggling. More at the Web Security hub.
Frequently asked questions#
What is CRLF injection?
CRLF injection abuses the carriage-return (\r) and line-feed (\n) characters that separate HTTP headers. If an application places unvalidated user input into a response header, an attacker can inject CRLF sequences to add their own headers or a response body — a technique called HTTP response splitting.
What can response splitting achieve?
By forging headers and body, an attacker can set malicious cookies, poison caches, redirect users, or inject a full response leading to cross-site scripting. It stems from trusting user input in a context — the header block — where line breaks have structural meaning.