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

Header Injection

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

Closest to 'specialist tool catches it' (d5), because the detection_hints list semgrep and psalm — both specialist SAST/static-analysis tools — as the means to catch unsanitised values passed to header(). It won't be caught by a default linter and is silent at runtime until exploited, so d5 is the right anchor.

e1 Effort Remediation debt — work required to fix once spotted

Closest to 'one-line patch or single-call swap' (e1), because the quick_fix states: strip or reject \r or \n from values passed to header(). In PHP 8.0+ the runtime throws automatically. This is a single sanitisation call at the point of use, well within e1 territory.

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

Closest to 'localised tax' (b3), because header() calls are confined to web-context PHP output logic (the applies_to context is 'web'). Once CRLF stripping is added at the relevant call sites, the rest of the codebase is unaffected. The fix doesn't spread across the architecture.

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

Closest to 'serious trap — contradicts how a similar concept works elsewhere' (t7), grounded in the misconception field: developers commonly believe header injection is merely a cosmetic formatting issue, when in fact injecting newlines enables full HTTP response splitting, XSS via reflected headers, cache poisoning, and open redirects. This dramatically underestimates severity, making it a serious cognitive trap just short of catastrophic.

About DEBT scoring →

Also Known As

HTTP header injection response header injection

TL;DR

User input included in an HTTP response header without stripping newlines enables response splitting and redirect hijacking.

Explanation

HTTP headers are separated by CRLF (\r\n). If an attacker injects a newline into a header value, they can inject additional headers or even a second HTTP response body — a technique called HTTP Response Splitting. This can be used to poison caches, hijack redirects, or inject HTML/JavaScript. Prevention: strip all \r and \n characters from any user-supplied value before including it in a header().

How It's Exploited

GET /page?lang=en%0d%0aSet-Cookie:admin=1
# Injects: Set-Cookie: admin=1 as a separate response header

Common Misconception

Header injection is just a cosmetic issue affecting formatting. Injecting newlines enables full HTTP response splitting, XSS via reflected headers, cache poisoning, and open redirect.

Why It Matters

Injecting headers via user input can redirect users, poison caches, or enable XSS through response splitting — all from a single unvalidated string.

Common Mistakes

  • Passing unsanitised user input to PHP's header() function, especially in Location or Set-Cookie headers.
  • Trusting X-Forwarded-For or Referer headers and reflecting them into responses.
  • Not stripping \r and \n from any value that ends up in an HTTP header.
  • URL-decoding values before passing to header() without re-stripping control characters.

Code Examples

✗ Vulnerable
// User input injected into header — attacker can inject newlines
$lang = $_GET['lang'];
header("Content-Language: $lang");
// ?lang=en%0d%0aSet-Cookie:admin=1  → injects extra header
✓ Fixed
// Allowlist approach
$allowed = ['en', 'fr', 'de', 'es', 'ja'];
$lang    = in_array($_GET['lang'] ?? 'en', $allowed, true)
           ? $_GET['lang'] : 'en';
header("Content-Language: $lang");

// If dynamic values are unavoidable, strip CR/LF:
$clean = str_replace(["\r", "\n"], '', $value);
header("X-Custom: $clean");

Added 15 Mar 2026
Edited 22 Mar 2026
Views 45
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings W 1 ping T 0 pings F 0 pings S 1 ping S 0 pings M 1 ping T 1 ping W 1 ping T 1 ping F 0 pings S 1 ping S 2 pings M 1 ping T 0 pings W 1 ping T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W
No pings yet today
No pings yesterday
Amazonbot 7 Scrapy 7 Ahrefs 4 ChatGPT 4 Google 2 Claude 2 Majestic 1 Perplexity 1 Meta AI 1 Bing 1 Qwen 1 PetalBot 1
crawler 27 crawler_json 5
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Low
⚡ Quick Fix
Strip or reject any \r or \n characters from values passed to header(); in PHP 8.0+ header() throws on CRLF automatically
📦 Applies To
PHP 5.0+ web
🔗 Prerequisites
🔍 Detection Hints
header( with user-supplied value not sanitised for CRLF characters
Auto-detectable: ✓ Yes semgrep psalm
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Low ✓ Auto-fixable Fix: Low Context: Line
CWE-113 CWE-644


✓ schema.org compliant