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

Header Injection

security CWE-113 OWASP A3:2021 CVSS 6.1 PHP 5.0+ Intermediate

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 20
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings W 0 pings T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 2 pings T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 1 ping W 0 pings T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T
No pings yet today
No pings yesterday
Amazonbot 6 Google 2 Ahrefs 2 ChatGPT 2 Majestic 1 Perplexity 1
crawler 12 crawler_json 2
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