CRLF Injection and HTTP Response Splitting

On this page
  1. How does it work?
  2. What can it lead to?
  3. How do you prevent CRLF injection?

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 contentImpact
Extra Set-CookieSession fixation, forced values
Location headerOpen redirect
Full response bodyReflected XSS, defacement
Cache-relevant headersCache poisoning

How do you prevent CRLF injection?#

  • Strip or reject \r and \n in 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.

Sources & further reading