# HTTP Response Splitting (CRLF injection) in report_story

Twitter's report_story endpoint reflected reported_tweet_id into a Set-Cookie header; UTF-8 overlong chars bypassed the 0x0a filter, enabling CRLF header injection.

- Payout: hidden
- Severity: medium
- Program: X / xAI
- Found by: filedescriptor
- Disclosed: 2015-04-21
- Write-up quality: 8/10
- Original: https://hackerone.com/reports/52042
- Library page: https://bugbountylibrary.com/r/h1%3A52042
- Tags: area:web domain:web impact:integrity kind:bounty platform:hackerone sev:medium technique:unicode-normalization vuln:crlf-injection

**Target:** Web endpoint /i/safety/report_story (reported_tweet_id parameter)
**Root cause:** The reported_tweet_id parameter is reflected into a Set-Cookie response header without numeric validation. A filter blocks literal newline (0x0a) but the app decodes UTF-8 to Unicode and extracts the last byte, so multi-byte sequences ending in 0x0a/0x0d slip through.
**Steps:**
1. Request `https://twitter.com/i/safety/report_story?next_view=report_story_start&source=reporttweet&reported_user_id=1&reporter_user_id=1&is_media=true&is_promoted=true&reported_tweet_id=%E5%98%8A%E5%98%8DSet-Cookie:%20test`
2. Observe the response contains an injected `Set-Cookie: test` header
3. Note `%E5%98%8A` decodes to U+560A whose last byte is 0x0A, bypassing the newline filter
**How found:** Noticed the parameter was reflected into a Set-Cookie header, tested a literal newline which was blocked, then reasoned the app converts UTF-8 back to Unicode and takes the last byte, allowing a multi-byte char ending in 0x0a to bypass the filter.
**Exploitation:** Attacker crafts a URL whose reported_tweet_id carries UTF-8 sequences decoding to CR/LF, injecting arbitrary response headers and body content into the victim's response, e.g. setting cookies or splitting the response.
**Insight:** When a filter blocks raw 0x0a/0x0d, try multi-byte UTF-8 sequences whose decoded codepoint's low byte is 0x0a or 0x0d (e.g. %E5%98%8A => U+560A) if the app re-encodes or truncates to a byte.

## Proof of concept (copied exactly from the original report)

**CRLF injection PoC URL setting arbitrary cookie**

```
https://twitter.com/i/safety/report_story?next_view=report_story_start&source=reporttweet&reported_user_id=1&reporter_user_id=1&is_media=true&is_promoted=true&reported_tweet_id=%E5%98%8A%E5%98%8DSet-Cookie:%20test
```

