CRLF injection happens when an application copies untrusted input into a context where carriage return and line feed characters act as delimiters, most damagingly into HTTP response headers, where it lets an attacker end the header block early or forge a second response. The weakness is old, but it keeps reappearing in redirect handlers, cookie-setting code, custom proxies, logging and anything that builds protocol text by string concatenation. This guide explains how the weakness works at the level a defender needs, where it hides in modern stacks, how to prevent it in code and at the edge, and how to detect and test for it within an authorised programme. It is written for application security engineers, developers, code reviewers and assessors. It contains no working payloads; for the wider family of web attacks see the Web Application Attacks Guide.
Key takeaways
- The root cause is a delimiter, not a header. MITRE describes CWE-93 as failing to neutralise CR and LF where they separate lines or records; HTTP headers (CWE-113), logs, email headers and line-based protocols are all sinks.
- The protocol already says no. RFC 9110 section 5.5 treats CR, LF and NUL in a field value as invalid and requires recipients to reject the message or replace them with a space; RFC 9113 makes such HTTP/2 messages malformed.
- Use the framework, never raw strings. The OWASP Web Security Testing Guide notes that built-in header APIs in modern environments typically block header injection; most real findings come from code that bypasses them.
- Redirects and cookies are the hot spots. OWASP names the
Locationheader (redirect targets taken from parameters) andSet-Cookieas the most common injection points. - Response splitting is a parsing-discrepancy problem. CAPEC-34 lists differences in how agents parse messages as a prerequisite, so consistent parsing across proxies, caches and servers is part of the fix.
How the weakness works
HTTP/1.1 separates header fields with CRLF and ends the header block with an empty line. If an application writes attacker-influenced data into a header value without neutralising CR and LF, the receiving agent may see the injected bytes as the end of one header and the start of another, or as the end of the headers and the start of a body. MITRE CWE-113 (Improper Neutralization of CRLF Sequences in HTTP Headers, previously named HTTP Request/Response Splitting) describes the result: the message is split and the attacker controls the second part.
| Term | Identifier | What it means | Main target |
|---|---|---|---|
| CRLF injection | CWE-93 | Any failure to neutralise CR and LF where they act as separators | Headers, logs, email, line protocols |
| HTTP header injection | CWE-113 | CR and LF from input reach outgoing HTTP headers | Clients, caches, intermediaries |
| HTTP response splitting | CAPEC-34 | One response is parsed as two or more by a client or intermediary | Users and shared caches |
| HTTP request splitting | CAPEC-105 | The same idea applied to requests a component sends onward | Back-end servers |
| Log injection | CAPEC-93, CWE-117 | CR and LF forge or split log entries; MITRE lists CWE-93 as able to precede CWE-117 | Log integrity and SOC analysts |
| HTTP request smuggling | CAPEC-33 | Front and back end disagree on message length; relies on framing differences rather than only special characters | Back-end connections |
Request smuggling is related but distinct: CAPEC notes it developed partly to bypass request-splitting defences. It has its own page, the HTTP Request Smuggling Guide, and this guide does not repeat it.
Impact: why it matters
The OWASP testing guide observes that the main victims are usually the application's users rather than the server. The documented consequences, from CWE-113, CAPEC-34 and OWASP WSTG-INJT-15, are:
- Web cache poisoning: a forged response stored by a shared cache or CDN is served to other users. See the Web Cache Poisoning and Cache Deception Guide.
- Cross-site scripting: CWE-113 can precede CWE-79, because injected content can land in a body the browser renders. See the Cross-Site Scripting (XSS) Prevention Guide.
- Cookie and session manipulation: an extra
Set-Cookieline can plant a value the victim's browser then sends back; OWASP lists session fixation among the outcomes. See the Session Fixation Guide. - Security header override: injected headers can change caching, content type or framing behaviour, undoing controls described in the Security Headers Guide.
- Content spoofing and defacement: CWE-113 examples include page hijacking and cross-user defacement.
- Log forging: fake entries mislead investigators or hide activity. See the Log Injection and Log Forging Guide.
Where it hides in modern applications
The OWASP testing guide notes that modern environments typically block header injection through their built-in header APIs, so the remaining risk sits in code paths that bypass or predate them. Review these sinks first:
| Sink | Typical source of input | Why it slips through | Preferred control |
|---|---|---|---|
Location in redirects | returnUrl, next, redirect parameters | Developers validate the destination host but not control characters, or decode the value twice | Allow-list destinations or map IDs to paths; URL-encode any dynamic part. See the Open Redirect Guide. |
Set-Cookie | Preferences, language, tracking values | Hand-built cookie strings | Framework cookie API with encoded values |
Content-Disposition | User-supplied file names | File name copied verbatim into the header | Server-generated names, or RFC 8187 encoding of the original name |
| Custom headers | Correlation IDs, tenant names, debug values echoed back | Treated as internal, so not validated | Strict pattern validation (for example UUID or token format) |
| Reverse proxies, gateways, serverless adapters | Headers forwarded or rewritten from upstream | Raw socket writes or response objects built from strings | Use the platform's header model; reject rather than repair invalid fields |
| Outbound HTTP clients | User data placed in headers sent to partners or internal APIs (request splitting) | Older client libraries that do not validate | Current, maintained client libraries; validate before setting |
| Logs and audit trails | Usernames, user agents, URLs | String concatenation into text logs | Structured logging with an encoder that escapes values |
| Email and other line protocols | Contact forms writing to Subject, To or custom headers | Mail libraries used at a low level | Library APIs that take addresses and subjects as separate fields |
Encoding traps: the WSTG remediation advice covers both raw and URL-encoded forms of CR and LF, and CWE-113 warns against decoding the same input twice. Validate after the final decode, in the representation that will be written to the header.
Prevention in code
- Set headers only through framework APIs. Never assemble a response as a string, and do not disable a framework's header validation for compatibility. Where a platform offers a relaxed or legacy parser option, keep it off.
- Reject, do not repair. Follow RFC 9110: an invalid field value is rejected or its CR, LF and NUL are replaced with a space. For application input, rejecting the request is clearer than silently stripping characters and is easier to log.
- Validate against what is expected. CWE-113 recommends accept-known-good validation. A language code, an ID or a redirect key has a narrow format; enforce it rather than block-listing characters.
- Encode dynamic parts of URLs and parameters. URL-encode values before they become part of a
Locationheader so control characters cannot act as delimiters, as WSTG advises. - Prefer indirection for redirects. Map a short key to a server-side list of permitted destinations instead of accepting full URLs.
- Encode for logs. The OWASP Logging Cheat Sheet recommends neutralising CR, LF and delimiter characters in event data and preferring structured formats such as JSON; it notes that parameterised logging alone does not stop CR and LF injection.
- Keep dependencies current. Header validation in web servers, frameworks and HTTP clients improves over time; older versions are where bypasses live.
Decision guidance: small teams on a single mainstream framework get most of the benefit from items 1, 4 and 6 plus dependency updates. Organisations running custom gateways, mixed HTTP/1.1 and HTTP/2 hops or legacy code should add the infrastructure controls below and targeted code review.
Prevention at the edge and in infrastructure
CAPEC-34's mitigations focus on removing the parsing discrepancies that make splitting useful.
- Normalise on HTTP/2 or HTTP/3 where possible: RFC 9113 section 8.2.1 says HTTP/2 field values must not contain NUL, LF or CR and that such messages are malformed, and section 8.2.2 makes connection-specific fields such as
Transfer-Encodingmalformed. CAPEC-34 recommends HTTP/2 for back-end connections. ASVS 5.0 V4.2.3 and V4.2.4 turn these into verification requirements. - Consistent parsing: CAPEC suggests the same server software, or at least the same strict parsing rules, along the request path, and having front ends flag and back ends reject ambiguous messages and close the connection.
- Protect intermediary-set headers: ASVS V4.1.3 requires that headers set by a load balancer, proxy or backend-for-frontend cannot be overridden by the end user.
- Caching rules: cache only responses that are safe to share, key caches on the inputs that change the response, and do not cache redirects built from user input. See the Web Cache Poisoning and Cache Deception Guide.
- WAF as a backstop: CAPEC lists a WAF that detects abnormal requests and responses; treat it as compensating while code is fixed, not as the fix. See the Bot Management vs WAF guide.
- Patch proxies and servers: CAPEC also lists applying vendor security updates to proxies and web servers.
Detection and testing
Testing must sit inside an authorised scope with written permission. The aim for defenders and assessors is to prove that CR and LF cannot reach a header, not to build an exploit chain.
| Method | What it finds | Strength | Limitation |
|---|---|---|---|
| SAST taint analysis | Flows from request input to header, cookie, redirect and log sinks | MITRE rates SAST effectiveness as high for CWE-113 | Misses sinks inside proxies or config; needs custom rules for in-house helpers |
| Manual code review | Hand-built responses, disabled validation, double decoding | Finds logic a scanner cannot model | Depends on reviewer time and checklists |
| DAST and authorised testing (OWASP WSTG-INJT-15) | Input reflected into response headers; whether CR and LF survive; impact on caches | Confirms exploitability end to end, including intermediaries | Only covers reachable endpoints and tested parameters |
| Edge and server telemetry | Requests carrying encoded CR or LF in parameters bound for redirect or cookie endpoints; 400 responses for malformed fields | Shows attempts in production | Attempts are not proof of a weakness |
| Log integrity checks | Entries with unexpected line breaks, or records that fail schema validation in structured logs | Catches log forging attempts | Only works if logs are structured |
Metrics that show the control is working:
- Open CWE-113 and CWE-93 findings by severity and age, with a target time to fix.
- Coverage: share of services with SAST rules for header, cookie, redirect and log sinks enabled in CI.
- Raw-response code paths: count of places that write responses or headers as strings, trending to zero.
- Structured logging adoption: share of services emitting structured, encoded logs.
- Edge rejects: volume of malformed-field rejections, watched for sudden rises that indicate probing.
Implementing it: a phased approach
- Inventory sinks: search code for direct response writes, manual header and cookie construction, redirect handlers and log calls that concatenate input. Tag custom proxies and gateways.
- Turn on detection: enable SAST rules for CWE-113, CWE-93 and CWE-117 in CI in report-only mode for one sprint to baseline findings, then fail builds on new high-severity findings.
- Fix by pattern: replace hand-built headers with framework calls, add allow-lists for redirect destinations, switch logs to structured encoders. Each fix ships with a unit test that confirms CR and LF are rejected.
- Harden the path: align parsing between edge and origin, prefer HTTP/2 for back-end connections, confirm intermediary headers cannot be overridden, and review cache rules for redirects.
- Verify: run authorised WSTG-INJT-15 testing on high-risk endpoints, including through the CDN and cache layers.
- Roll back safely: stricter rejection can break legacy clients or partners that send malformed fields; deploy edge rejection in log-only mode first, review the hits, then enforce per route.
Framework mapping
| Framework | Reference | Relevance |
|---|---|---|
| MITRE CWE | CWE-93, CWE-113, CWE-117 | Root weakness, HTTP header case, log neutralisation |
| MITRE CAPEC | CAPEC-34, CAPEC-105, CAPEC-93 | Response splitting, request splitting, log injection patterns |
| OWASP ASVS 5.0 | V1.2.1 | Context-relevant output encoding, including HTTP header fields |
| OWASP ASVS 5.0 | V4.1.3, V4.2.3, V4.2.4 | Intermediary headers not user-overridable; no connection-specific fields in HTTP/2 and HTTP/3; reject CR and LF in header fields |
| OWASP ASVS 5.0 | V16.4.1 | Logging components encode data to prevent log injection |
| OWASP WSTG | WSTG-INJT-15 | Testing for HTTP response splitting |
| NIST SP 800-53 Rev. 5 | SI-10, SI-15 | Information input validation; information output filtering |
| NIST CSF 2.0 | PR.PS-06 | Secure software development practices integrated into the life cycle |
Common failure patterns
- Validating the host, not the bytes: a redirect check confirms the destination domain but lets control characters through in the path or query.
- Double decoding: input is validated, then decoded again by a later layer, reintroducing CR and LF that the check never saw.
- Custom response writers: a performance-tuned handler or legacy adapter writes headers as raw text, bypassing the framework's validation.
- Silent stripping: removing CR and LF without logging hides probing and can produce unexpected values; reject and record instead.
- Relying on the WAF: edge rules catch obvious encodings while the underlying sink stays in the code.
- Text logs built by concatenation: usernames or user agents with embedded line breaks forge entries that mislead incident responders.
Practitioner checklist
- Set all response headers and cookies through framework APIs; ban raw response writing in code review.
- Keep framework header validation and strict parsers enabled; never switch on legacy or relaxed parsing modes in production.
- Allow-list or map redirect destinations and URL-encode any dynamic component.
- Validate header-bound input against an expected format after the final decode.
- Use structured, encoded logging for all event data.
- Enable SAST rules for CWE-113, CWE-93 and CWE-117 and track findings to closure.
- Align parsing between edge and origin, prefer HTTP/2 to back ends, and protect intermediary-set headers.
- Include WSTG-INJT-15 in authorised testing of redirect, cookie and download endpoints, through the cache layer.
Standards and references
- MITRE: CWE-113 Improper Neutralization of CRLF Sequences in HTTP Headers
- MITRE: CWE-93 Improper Neutralization of CRLF Sequences
- MITRE CAPEC: HTTP Response Splitting
- IETF: RFC 9110 HTTP Semantics
- IETF: RFC 9113 HTTP/2
- OWASP: Web Security Testing Guide, HTTP Response Splitting
- OWASP: Application Security Verification Standard 5.0
- OWASP: Logging Cheat Sheet
Related NHI Mgmt Group resources: Web Application Attacks Guide · HTTP Request Smuggling Guide · Session Fixation Guide · Host Header Attacks and Validation Guide