Protocol, Config & Infra Injection (long tail)
§Basic information
This is the catch-all bucket for bugs that cross a protocol or serialization boundary rather than a single web-vuln taxonomy: a byte you control (usually \r/\n, sometimes a whitespace or Unicode look-alike) is written verbatim into a structured stream — an HTTP header block, an INI/YAML config file, a live SMTP or LDAP session, a proxy's request framing — and reframes that stream into something the parser on the other side treats as new commands, new headers, or a new request. The same class covers the infrastructure long tail: DNS/subdomain takeover, unthrottled brute-force of sensitive gates, and TLS/cert-validation logic that returns success while skipping the check.
The recurring, transferable primitive is "a sink that trusts a data type, or a field its sibling fields don't." A sanitizer written for a String stops running when a framework upgrade starts passing an Array (#2279572); one config field skips the newline check every other field enforces (#1054282, #1200647); one code path narrows a Unicode code point to a raw CR byte after the ASCII filter already ran (#409943). These are low-severity-looking primitives that chain to the highest-impact outcomes in the corpus — a single \r\n in a Grafana SMTP password field became RCE (#1200647).
§Methodology
- Identify the boundary your input crosses. Not "is this reflected" but into what stream — an HTTP response header, a config-file line, an SMTP/LDAP command, a proxy's request framing, a DNS delegation.
- Fire an inert canary for that boundary (CRLF, an OWS-before-colon, a quoted-comment email, an
X-Forwarded-Host) and grep the raw response/logs/error banner for a new line, header, or reflected backend banner. - Enumerate the newline variants separately —
%0d%0a, lone%0d, lone%0a, folded%0d%0a%09— because different hops enforce different rules and they are not interchangeable. - Hunt the type/sibling gap. Whenever a value type-dispatches (
case value when Array … when /\n/ …) or one field's validation differs from its siblings, that branch is the hole. - Escalate to the boundary's native impact — response splitting → XSS, config-section injection → RCE, SMTP/RESP smuggling → send-as/webshell, cache poisoning → mass/stored.
- For infra (DNS, brute gates, TLS), the "canary" is enumeration:
dig NS, an Intruder run against a re-auth endpoint, a--curveserror path.
§Injection contexts
Find which boundary your input reaches, then use the matching breakout.
CRLF into an HTTP response header
Any parameter, path segment, or header value reflected into Location/Set-Cookie/a canonical link. Inject \r\n to add headers; \r\n\r\n to break into the body and plant XSS.
Array elements; pitchfork's append_header only stripped newlines in its String branch, so the when /\n/ guard became unreachable and a "fixed" response-splitting bug silently reopened (#2279572, CVE-2025-30221).CRLF into a config-file serializer
A setting whose value lands in an INI/YAML/env file. A newline lets you start a new section and set non-exported keys the UI never exposes — the highest-value variant.
CRLF into an internal protocol connector (gopher-style)
A config field or URL that reaches an internal service connector lets you frame the target protocol (RESP/SMTP/postgres) with URL-encoded CRLF and speak it to localhost.
Newline into a live SMTP session
An attacker-supplied email address placed into an already-authenticated RCPT TO:<…> without stripping \r\n. Wrap the payload so it passes the app's email regex yet still emits a newline to the server.
Whitespace-before-colon proxy desync
Don't only vary TE/CL values — vary the optional whitespace (OWS) around the colon, an octet class RFC 7230 forbids but hops disagree on. A front proxy (Squid) and the downstream actor split the header block differently → smuggling.
Unicode narrowing to CRLF
When ASCII CR/LF is filtered, high code points whose low byte is 0x0d/0x0a reconstitute when the string is narrowed to bytes at the socket. Same trick works on any layer doing lossy Unicode→byte conversion.
DNS / subdomain takeover
Enumerate NS/CNAME per subdomain and look for a delegation with no live backing zone. NS-level takeover is broader than CNAME — you own every record in the zone.
Unthrottled sensitive gates
Re-auth prompts and OTP flows that lack the rate limiting the main login has. Test verify and resend as a pair — throttling verify is meaningless if resend refreshes the code and resets the attempt budget.
§Bypasses
Each tagged with the report it came from.
| Filter / control | Bypass | Seen in |
|---|---|---|
String-only newline guard | Rack 3 passes header values as Array; the when /\n/ branch is unreachable, so no sanitization runs | #2279572 |
| App-side email validator | quoted local part / (comment) satisfies the regex yet still emits \r\n to the SMTP server | #1509216 |
| ASCII CRLF filter | Unicode code points (Ġ/č/Ċ) narrowed to 0x20/0x0d/0x0a at the socket | #409943 |
| Sibling-field newline check | one config field (LDAP/SMTP password) skipped the check every other field enforced | #1054282, #1200647 |
Lone \r blocked by nginx | use full \r\n or a lone \n — nginx forwards both but blocks a bare \r | #2279572 |
| CRLF stripped in header value | folded-header continuation %0d%0a%09<name>:<value> (leading TAB) | #858650 |
| Cache not keyed on header | loop requests with X-Forwarded-Host until cached, then drop the header — the value persists | #977851 |
| RFC-strict header parsing | invalid OWS / pseudo-space before the colon (\t \x0b \f \r) desyncs the hops | #758445 |
| Basic-auth "gate" | Django DRF /api-auth/login/ reachable even after cancelling the basic-auth prompt | #128114 |
| C error-path result reuse | early result=0 makes a later bare goto out return CURLE_OK, skipping cert verify | #2410774 |
| Username uniqueness check | Unicode confusables & invisibles bypass validation → impersonation/collision | #3434156 |
| AWS STS token validation | case-collision parameter smuggling bypasses the validation check | #1580493 |
#192749, #977851), and same-site cookie tossing (Domain=.target, scoped Path=) fires a CSP-less HTML preview as the victim (#3594137). Report the delivery vector with the primitive.§Escalation & impact
Almost every headliner here is a stepping stone, not the destination: