-
Notifications
You must be signed in to change notification settings - Fork 14
Reject control chars in request headers #4565
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -490,7 +490,7 @@ internal static void CheckPath(string path) | |
| if (path.Length == 0 || path[0] != '/' || !IsValid(path, _notValidInPath)) | ||
| { | ||
| throw new FormatException( | ||
| $"Invalid path '{path}'; a valid path starts with '/' and contains only unreserved characters, '%', and reserved characters other than '?' and '#'."); | ||
| "Invalid path; a valid path starts with '/' and contains only unreserved characters, '%', and reserved characters other than '?' and '#'."); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think printing the 'invalid path' (like we did before) would be a valuable piece of information for debugging. I recognize there's a tradeoff where: if there's control characters, the message might look weird. but I think the benefit of seeing "oh, |
||
| } | ||
| } | ||
|
|
||
|
|
@@ -501,6 +501,23 @@ internal static void CheckPath(string path) | |
| /// <see langword="false" />.</returns> | ||
| internal static bool IsValidParamValue(string value) => IsValid(value, _notValidInParamValue); | ||
|
|
||
| /// <summary>Checks if <paramref name="operation" /> is a valid operation name. A valid operation name contains | ||
| /// only printable ASCII characters (in the inclusive range <c>0x21</c> to <c>0x7E</c>) and may be empty. | ||
| /// </summary> | ||
| /// <param name="operation">The operation name to check.</param> | ||
| /// <exception cref="FormatException">Thrown if the operation name is not valid.</exception> | ||
| /// <remarks>This range covers every legal Slice identifier and rejects all C0 control characters as well as DEL | ||
| /// and any non-ASCII content. Empty operation names are accepted because <see cref="OutgoingRequest.Operation" /> | ||
| /// defaults to the empty string.</remarks> | ||
| internal static void CheckOperation(string operation) | ||
| { | ||
| if (operation.AsSpan().IndexOfAnyExceptInRange(FirstValidChar, LastValidChar) != -1) | ||
| { | ||
| throw new FormatException( | ||
| "Invalid operation name; an operation name contains only printable ASCII characters."); | ||
| } | ||
| } | ||
|
|
||
| /// <summary>"unchecked" constructor used by the Ice decoder when decoding a service address. | ||
| /// </summary> | ||
| internal ServiceAddress( | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure that IceRPC has the same restriction as Ice here. i.e. ascii only characters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For Path we already have this check in ServiceAddress, so it makes sense we don't accept paths that are not valid according to the ServiceAddress rules.
For Operation I guess we didn't really specify what a valid operation names is in the "icerpc" protocol, at the protocol level is just a string. And this should probably be handled in the integration layer if at all, for example Slice operations are derived from Slice identifiers and have the same limitations that the identifier has. Same for Protobuf, they are derived from the Protobuf IDL and have its own rules.
I think is probably wrong to check the operation name here, as the protocol layer doesn't specify what the operation name is, checking the path seems correct because ServiceAddress format is specified in the protocol.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I couldn't find anywhere in the docs were we way we only accept ASCII chars (but maybe its there?).
Is this check really required here? ServiceAddress' Path init function already does this check, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ServiceAddress is not used here, we decode the Path as a string, using IceRpcRequestHeader
icerpc-csharp/slice/IceRpc/Internal/IceRpcDefinitions.slice
Lines 21 to 26 in 0909b4b
Then the path string is assigned to
IncomingRequest.Path, another string without further validation.icerpc-csharp/src/IceRpc/IncomingRequest.cs
Line 43 in 0909b4b
Maybe is clear to move the validation to
IncomingRequest.PathinitThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. Yeah it would make sense to also have it there.
Reminds me of https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate