# CRLF injection into protocol streams

User text concatenated into SMTP, Redis, config or XML streams without rejecting CR, LF or NUL

_Area: Web injection and code execution. Seen in 8 disclosed reports; latest 2026-09-08. Updated 2026-10-23._

## How it works
A protocol stream is a sequence of lines or length-prefixed frames. When a program builds that stream by concatenating user-controlled text, it assumes the text contains no line breaks. If the text does contain CR/LF, the receiver treats the remainder as a new command, directive or markup. The same failure appears when a validator is meant to check the whole string but actually checks each line, or when a writer re-serializes stored values without re-checking them. A related shape: a client that re-parses its own serialized buffer by splitting on CRLF instead of honoring length prefixes creates a parser differential with the server [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-w6f5-v2h6-g786.md).

## Where it shows up
- Fields pipelined into SMTP envelope commands (booking email into RCPT TO) [E3](https://bugbountylibrary.com/r/h1%3A1509216.md); iCalendar ORGANIZER mailto into pipelined SMTP [E8](https://bugbountylibrary.com/r/h1%3A1516377.md)
- Client libraries that re-parse their own serialized buffer by splitting on CRLF instead of honoring length prefixes [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-w6f5-v2h6-g786.md)
- Config writers that re-emit values read from disk, where the injection guard covers only setter arguments [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-284h-m62q-gf8w.md)
- Anchored `^...$` regexes compiled with the `m` flag, so one valid line plus a terminator passes [E5](https://bugbountylibrary.com/r/ghsa%3AGHSA-jxjr-3g7g-3944.md)[E6](https://bugbountylibrary.com/r/ghsa%3AGHSA-vr34-hp96-76pp.md)[E7](https://bugbountylibrary.com/r/ghsa%3AGHSA-3px3-54cx-rmw9.md)
- A config field later reused as a credential in an outbound protocol handshake, unvalidated unlike its siblings [E4](https://bugbountylibrary.com/r/h1%3A1054282.md)

## How to review
Find every place user-controlled text enters a protocol or markup stream. The invariant: the value must be validated as a whole string, and any CR, LF or NUL must be rejected or encoded before concatenation. Check that validation runs on the exact bytes written, not on a parsed or re-serialized copy. For regex validators, confirm no `m`/`s` flag turns anchors into line anchors. For writers, confirm values loaded from disk pass the same guard as setter input. For config fields, confirm every sibling field gets the same newline check, not just the obvious ones.

## Variants seen
- SMTP command injection via newlines in an email field [E3](https://bugbountylibrary.com/r/h1%3A1509216.md)
- SMTP command injection via newlines in an iCalendar ORGANIZER address [E8](https://bugbountylibrary.com/r/h1%3A1516377.md)
- Redis command smuggling through CRLF in keys/values on aggregate connections [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-w6f5-v2h6-g786.md)
- Dormant multi-line config value becoming a live directive on write [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-284h-m62q-gf8w.md)
- Line-terminator bypass of QName and DocType validators [E5](https://bugbountylibrary.com/r/ghsa%3AGHSA-jxjr-3g7g-3944.md)[E6](https://bugbountylibrary.com/r/ghsa%3AGHSA-vr34-hp96-76pp.md)[E7](https://bugbountylibrary.com/r/ghsa%3AGHSA-3px3-54cx-rmw9.md)
- Unvalidated LDAP password reused in outbound protocol handshake [E4](https://bugbountylibrary.com/r/h1%3A1054282.md)

## Why fixes fail
Guards scoped to one field or one path leave siblings open: setter-only checks miss read-then-write [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-284h-m62q-gf8w.md); a shared regex builder kept the `m` flag across validators [E5](https://bugbountylibrary.com/r/ghsa%3AGHSA-jxjr-3g7g-3944.md)[E6](https://bugbountylibrary.com/r/ghsa%3AGHSA-vr34-hp96-76pp.md)[E7](https://bugbountylibrary.com/r/ghsa%3AGHSA-3px3-54cx-rmw9.md); one LDAP field lacked the newline check its siblings had [E4](https://bugbountylibrary.com/r/h1%3A1054282.md).

## Impact and severity
High: authenticated SMTP hijack [E3](https://bugbountylibrary.com/r/h1%3A1509216.md)[E8](https://bugbountylibrary.com/r/h1%3A1516377.md), Redis command injection and DoS wiping cluster shards [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-w6f5-v2h6-g786.md), hook-based RCE requiring a later write [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-284h-m62q-gf8w.md), XML markup injection [E5](https://bugbountylibrary.com/r/ghsa%3AGHSA-jxjr-3g7g-3944.md)[E6](https://bugbountylibrary.com/r/ghsa%3AGHSA-vr34-hp96-76pp.md)[E7](https://bugbountylibrary.com/r/ghsa%3AGHSA-3px3-54cx-rmw9.md), and protocol smuggling to internal services reaching RCE [E4](https://bugbountylibrary.com/r/h1%3A1054282.md). Severity rises when the injected stream carries an authenticated session or reaches a privileged sink.

## Evidence
- E1: https://bugbountylibrary.com/r/ghsa%3AGHSA-w6f5-v2h6-g786.md
- E2: https://bugbountylibrary.com/r/ghsa%3AGHSA-284h-m62q-gf8w.md
- E3: https://bugbountylibrary.com/r/h1%3A1509216.md
- E4: https://bugbountylibrary.com/r/h1%3A1054282.md
- E5: https://bugbountylibrary.com/r/ghsa%3AGHSA-jxjr-3g7g-3944.md
- E6: https://bugbountylibrary.com/r/ghsa%3AGHSA-vr34-hp96-76pp.md
- E7: https://bugbountylibrary.com/r/ghsa%3AGHSA-3px3-54cx-rmw9.md
- E8: https://bugbountylibrary.com/r/h1%3A1516377.md
