Glyph11 provides two layers of defense against HTTP/1.1 protocol attacks:
- Parse-time validation (
HardenedParser) — rejects malformed input during parsing - Post-parse validation (
RequestSemantics) — detects semantically dangerous patterns after parsing
These checks are enforced automatically during TryExtractFullHeader / TryExtractFullHeaderROM. Violations throw HttpParseException.
Attack: HTTP request smuggling via bare line feed (0x0A without preceding 0x0D). Some parsers accept bare LF as a line terminator while others require CRLF, creating parsing discrepancies.
RFC: 9112 Section 2.2 — "A recipient of such a bare CR MUST consider that element to be invalid."
Protection: The parser checks each parsed line for bare LF (0x0A) using vectorized IndexOf. Any bare LF causes immediate rejection.
CVEs prevented: CVE-2023-30589 (Node.js), CVE-2025-58056 (Netty), CVE-2019-16785 (Waitress).
Attack: Header value continuation lines (starting with SP or HTAB) can obfuscate Transfer-Encoding headers to create smuggling vectors.
Transfer-Encoding: chunked\r\n
Garbage\r\n
RFC: 9112 Section 5.2 — "A server that receives an obs-fold in a request message MUST either reject the message... or replace each received obs-fold."
Protection: Any header line starting with SP (0x20) or HTAB (0x09) is rejected.
Attack: Content-Length : 0 (space before colon) may be accepted by some parsers but rejected by others, enabling TE.TE smuggling.
RFC: 9112 Section 5.1 — "No whitespace is allowed between the field name and colon."
Protection: The parser checks the byte immediately before the colon in each header line and rejects if it is SP or HTAB.
Attack: Multiple spaces between request-line components (GET /path HTTP/1.1) create parsing ambiguity that can lead to request smuggling.
RFC: 9112 Section 3 — request-line = method SP request-target SP HTTP-version
Protection: After finding the space delimiters, the parser verifies no additional spaces follow immediately.
Attack: Control characters (0x00-0x1F, 0x7F) in the URL enable null-byte path truncation and injection.
RFC: 9112 Section 3.2 — request-target must contain only valid URI characters.
Protection: The request-target is validated using SIMD-accelerated SearchValues<byte>; any control character causes rejection.
Attack: Invalid characters in HTTP methods can confuse downstream processing.
RFC: 9110 Section 5.6.2 — method is a token (!#$%&'*+-.^_|~ DIGIT ALPHA`).
Protection: The method is validated against the RFC 9110 token character set using SIMD-accelerated SearchValues<byte>.
Attack: Control characters or invalid bytes in header names create parsing discrepancies between systems.
RFC: 9110 Section 5.1 — field-name is a token.
Protection: Each header name is validated against the token character set using SIMD-accelerated SearchValues<byte>.
Attack: CRLF injection, null byte injection, and control character injection in header values.
RFC: 9110 Section 5.5 — field-value allows only HTAB (0x09), SP (0x20), VCHAR (0x21-0x7E), and obs-text (0x80-0xFF).
Protection: Each header value is validated against the allowed character set using SIMD-accelerated SearchValues<byte>. CR, LF, NUL, and all other control characters are rejected.
CVEs prevented: CVE-2024-52875, CVE-2024-20337.
Attack: A header line starting with : (empty name) causes undefined behavior in different parsers.
RFC: 9110 Section 5.1 — field-name requires at least one token character.
Protection: Header lines where the colon is at position 0 are rejected.
Attack: Header lines without a colon separator may be silently dropped by lenient parsers, creating discrepancies.
Protection: Any header line that does not contain a colon is rejected with an exception (not silently skipped).
Attack: Invalid version strings enable protocol downgrade attacks and undefined behavior.
RFC: 9112 Section 2.6 — HTTP-version = "HTTP/" DIGIT "." DIGIT
Protection: The version string must be exactly 8 bytes matching HTTP/X.Y where X and Y are ASCII digits.
All limits are configurable via ParserLimits:
| Limit | Default | Attack Prevented |
|---|---|---|
MaxHeaderCount |
100 | Header flooding |
MaxHeaderNameLength |
256 | Oversized header names |
MaxHeaderValueLength |
8192 | Oversized header values |
MaxUrlLength |
8192 | URL buffer overflow |
MaxQueryParameterCount |
128 | Query parameter flooding |
MaxMethodLength |
16 | Oversized method strings |
MaxTotalHeaderBytes |
32768 | Total header section DoS |
These checks are called explicitly after successful parsing. Each returns true if the attack pattern is detected.
Attack: CL.TE / TE.CL request smuggling. When both Transfer-Encoding and Content-Length are present, front-end and back-end may disagree on message body boundaries.
RFC: 9112 Section 6.1
Attack: Multiple Content-Length headers with different values. One system uses the first value, another uses the last.
RFC: 9110 Section 8.6
Attack: A single Content-Length header with comma-separated values that differ (e.g. Content-Length: 42, 0).
RFC: 9112 Section 6.2
Attack: Non-digit characters in Content-Length values (Content-Length: abc, Content-Length: 1 2, Content-Length: 1e5). Different parsers interpret these differently.
RFC: 9110 Section 8.6 — Content-Length is 1*DIGIT.
CVEs prevented: CVE-2018-7159 (Node.js).
Attack: Content-Length: 0200 may be interpreted as decimal 200 by one parser but octal 128 by another.
RFC: 9110 Section 8.6
Attack: TE.TE smuggling via obfuscated Transfer-Encoding values (xchunked, "chunked", chunked-thing). One system recognizes it as chunked, another does not.
RFC: 9112 Section 6.1
Attack: Missing Host header (routing confusion) or multiple Host headers (routing disagreement between front-end and back-end, SSRF).
RFC: 9112 Section 3.2 — exactly one Host header required for HTTP/1.1.
Attack: /../ and /./ sequences in the path allow directory traversal to access files outside the intended root.
RFC: 3986 Section 5.2.4
Attack: Backslash characters (\) are treated as path separators on Windows, enabling traversal via \..\.
Attack: %252e%252e decodes to %2e%2e after one pass, then .. after a second. Bypasses single-decode security filters.
Attack: %00 in the path causes C-based file systems to truncate the path at the null byte. file.txt%00.jpg passes extension checks but opens file.txt.
Attack: Overlong UTF-8 sequences encode ASCII characters (like / as 0xC0 0xAF) to bypass ASCII-only path checks.
RFC: 3629 Section 3 — overlong sequences are forbidden.
Attack: Fragment identifiers (#) must not appear in HTTP request-targets. Their presence indicates injection or malformed input.
RFC: 9112 Section 3.2
using Glyph11;
using Glyph11.Parser.Hardened;
using Glyph11.Validation;
var limits = ParserLimits.Default;
if (HardenedParser.TryExtractFullHeader(ref buffer, request, in limits, out var bytesRead))
{
// Parse-time checks already passed (method, headers, version, limits, etc.)
// Now run post-parse semantic checks:
if (RequestSemantics.HasInvalidHostHeaderCount(request))
throw new HttpParseException("Invalid Host header count.");
if (RequestSemantics.HasTransferEncodingWithContentLength(request))
throw new HttpParseException("Request smuggling: TE + CL.");
if (RequestSemantics.HasConflictingContentLength(request))
throw new HttpParseException("Conflicting Content-Length values.");
if (RequestSemantics.HasConflictingCommaSeparatedContentLength(request))
throw new HttpParseException("Conflicting comma-separated Content-Length.");
if (RequestSemantics.HasInvalidContentLengthFormat(request))
throw new HttpParseException("Invalid Content-Length format.");
if (RequestSemantics.HasContentLengthWithLeadingZeros(request))
throw new HttpParseException("Content-Length has leading zeros.");
if (RequestSemantics.HasInvalidTransferEncoding(request))
throw new HttpParseException("Invalid Transfer-Encoding value.");
if (RequestSemantics.HasDotSegments(request))
throw new HttpParseException("Path traversal detected.");
if (RequestSemantics.HasBackslashInPath(request))
throw new HttpParseException("Backslash in path.");
if (RequestSemantics.HasDoubleEncoding(request))
throw new HttpParseException("Double encoding detected.");
if (RequestSemantics.HasEncodedNullByte(request))
throw new HttpParseException("Encoded null byte in path.");
if (RequestSemantics.HasOverlongUtf8(request))
throw new HttpParseException("Overlong UTF-8 in path.");
if (RequestSemantics.HasFragmentInRequestTarget(request))
throw new HttpParseException("Fragment in request-target.");
// Safe to process request
}| Category | Parse-Time | Post-Parse |
|---|---|---|
| HTTP Request Smuggling (CL.TE, TE.CL, TE.TE) | X | |
| CRLF / Header Injection | X | |
| Bare LF Smuggling | X | |
| Obs-fold Smuggling | X | |
| Header Name Injection | X | |
| Header Value Injection | X | |
| Content-Length Manipulation | X | |
| Transfer-Encoding Obfuscation | X | |
| Host Header Attacks | X | |
| Path Traversal | X | |
| Null Byte Injection | X | X |
| Double Encoding Bypass | X | |
| Overlong UTF-8 Bypass | X | |
| Backslash Traversal | X | |
| Fragment Injection | X | |
| Resource Exhaustion (DoS) | X | |
| HTTP Version Manipulation | X | |
| Request Line Injection | X |