CRLF Injection
debt(d5/e3/b3/t5)
Closest to 'specialist tool catches' (d5). The term's detection_hints lists semgrep and psalm as tools that can detect header() calls with user-supplied values containing potential newlines. These are SAST tools that require explicit configuration, not default linters. PHP 8.0+ throws on CRLF automatically, but older versions need these specialist tools to catch the vulnerability.
Closest to 'simple parameterised fix' (e3). The quick_fix states to strip or reject \r and \n from user input used in HTTP headers. This is a localised sanitisation pattern applied to header() and setcookie() calls, typically requiring a helper function and updating a handful of call sites within input validation or header-setting code — more than one line but contained to specific areas.
Closest to 'localised tax' (b3). The term applies_to web contexts only, and the fix is specifically about HTTP header handling. Once proper input sanitisation is applied to header-setting code, the rest of the codebase is unaffected. The burden doesn't spread across all development work — it's a specific concern at the HTTP boundary layer.
Closest to 'notable trap' (t5). The misconception explicitly states that developers think CRLF injection is 'just a minor header formatting issue' when it actually enables XSS, cache poisoning, and session fixation via response splitting. This is a documented gotcha that security-aware developers eventually learn, but the severity gap between perception and reality is significant.
Also Known As
TL;DR
Explanation
CRLF injection (\r\n) exploits insufficient sanitisation of newline characters in values that end up in HTTP response headers. An attacker who can inject \r\n can terminate the current header and begin a new one — or even split the response body to deliver a second HTTP response (HTTP Response Splitting). In PHP, header() strips newlines since PHP 7.4, but older codebases and custom header construction remain vulnerable. Always strip \r and \n from any user-supplied value before embedding it in a header.
Common Misconception
Why It Matters
Common Mistakes
- Allowing newline characters in any value passed to PHP's header() function.
- URL-decoding user input before passing to header() — %0d%0a is the encoded CRLF.
- Reflecting redirect targets directly into Location headers without stripping control characters.
- Not stripping \r and \n from user-supplied filenames in Content-Disposition headers.
Code Examples
header('Location: ' . $_GET['url']); // \r\n in url splits response
$url = str_replace(["\r", "\n"], '', $_GET['url']);
header('Location: ' . $url);