Document TryAddWithoutValidation security implications and validation behavior
TryAddWithoutValidation methods perform header name validation but skip header value validation, creating security risks when used with untrusted input. This was undocumented.
Changes
-
Clarified validation behavior: Header names are validated (returns
falsefor invalid names), but header values are not - Added security warning: Values must be trusted or validated to prevent protocol-level attacks
-
Provided minimum validation guidance: Prohibit newline characters (
\r,\n,\0) to prevent request smuggling:if (value.IndexOfAny(new[] { '\r', '\n', '\0' }) >= 0) throw ... -
Documented observable behavior: Unvalidated values appear in enumeration and queries, even without using
NonValidatedview
Both TryAddWithoutValidation overloads now have identical, comprehensive remarks sections explaining these behaviors.
Original prompt
Improve the TryAddWithoutValidation docs.
Here are the relevant sections from internal documentation:
TryAddWithoutValidationmethods do perform header name validation, returningfalsefor invalid names.
TryAddWithoutValidationmethods do not perform any header value validation. Values added via these methods are assumed to be trusted, and other application logic, such as HttpClient, may misbehave if they are not well formed. In particular, callers are highly encouraged to validate that these values not contain new line characters to guard against attacks such as request smuggling.
Values added without validation may be observed when enumerating the collection or querying for the specific header name, even when the caller is not using theHttpHeaders.NonValidatedview of the collection.
TryAddWithoutValidationmust never be used with untrusted values, unless it was otherwise sufficiently validated.
What constitutes "sufficient" validation can vary by use case. At a minimum, prohibit new line characters for protocol correctness, e.g.if (value.ContainsAny('\r', '\n', '\0')) throw .... This should ensure that the server application sees values in the same way as the client application, with the server now being responsible for properly sanitizing its own inputs.
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.