← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

CRLF Injection

Security CWE-93 OWASP A3:2021 CVSS 6.1 PHP 5.0+ Intermediate
debt(d5/e3/b3/t5)
d5 Detectability Operational debt — how invisible misuse is to your safety net

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.

e3 Effort Remediation debt — work required to fix once spotted

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.

b3 Burden Structural debt — long-term weight of choosing wrong

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.

t5 Trap Cognitive debt — how counter-intuitive correct behaviour is

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.

About DEBT scoring →

Also Known As

HTTP response splitting CRLF attack newline injection

TL;DR

Injecting carriage-return and line-feed characters into HTTP headers splits responses or injects new headers, enabling log poisoning and XSS.

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

CRLF injection is just a minor header formatting issue. An attacker controlling a response header can inject a full second HTTP response, enabling XSS, cache poisoning, and session fixation.

Why It Matters

Injecting carriage return and line feed characters into HTTP responses lets attackers add arbitrary headers, split responses, or inject JavaScript — bypassing security controls that rely on headers.

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

✗ Vulnerable
header('Location: ' . $_GET['url']); // \r\n in url splits response
✓ Fixed
$url = str_replace(["\r", "\n"], '', $_GET['url']);
header('Location: ' . $url);

Added 15 Mar 2026
Edited 4 Jun 2026
Views 172
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 1 ping W 2 pings T 1 ping F 1 ping S 0 pings S 0 pings M 0 pings T 2 pings W 2 pings T 3 pings F 1 ping S 1 ping S 2 pings M 1 ping T 0 pings W 1 ping T 1 ping F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 2 pings S 1 ping S 0 pings M 2 pings T 1 ping W
ChatGPT 1
PetalBot 1 Perplexity 1
ChatGPT 68 Perplexity 21 Scrapy 10 Amazonbot 8 Google 7 SEMrush 5 Ahrefs 3 Unknown AI 2 Claude 2 Bing 2 PetalBot 2 Qwen 1 Meta AI 1
crawler 129 crawler_json 3
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Low
⚡ Quick Fix
Strip or reject \r and \n from any user input used in HTTP headers — in PHP 8.0+ header() throws on CRLF automatically, but validate explicitly for older code
📦 Applies To
PHP 5.0+ web
🔗 Prerequisites
🔍 Detection Hints
header() with user-supplied value containing potential newlines; setcookie() with unsanitised name or value
Auto-detectable: ✓ Yes semgrep psalm
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Low ✓ Auto-fixable Fix: Low Context: Line
CWE-93 CWE-113


✓ schema.org compliant