fix: avoid unescaping slashes when proxying URLs#1134
Open
refi64 wants to merge 1 commit intoory:masterfrom
Open
fix: avoid unescaping slashes when proxying URLs#1134refi64 wants to merge 1 commit intoory:masterfrom
refi64 wants to merge 1 commit intoory:masterfrom
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1134 +/- ##
==========================================
- Coverage 77.90% 77.74% -0.17%
==========================================
Files 80 79 -1
Lines 3929 4040 +111
==========================================
+ Hits 3061 3141 +80
- Misses 595 618 +23
- Partials 273 281 +8 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
276c9bc to
2e4ed10
Compare
Doing all the path operations on URL.Path means that they're being performed on an unescaped URL. Unfortunately, this URL is *not* guaranteed to be the directly unescaped version of URL.EscapedPath(); in particular, slashes will be unescaped in URL.Path, e.g. given: /abc%2Fdef URL.Path will be: /abc/def In these cases, URL.RawPath is also set with the escaped version of the path. However, once URL.Path is modified, URL.RawPath is ignored, and URL.EscapedPath() returns the path-escaped version of URL.Path...which, in this case, is now /abc/def, not the correct /abc%2Fdef. As a result, when performing any path modifications during proxying (i.e. proxying to an upstream URL with a path component, or applying StripPath), this results in any *escaped* slashes in the proxied URL being unescaped. In order to work around this, rewriting operations need to take place on the *escaped* path, not the unescaped one, and then an intermediate URL can be used to determine the Path and RawPath values to set on the forward URL. This incurs a small breaking change in that StripPath is now applied to the *escaped* URL, not the unescaped URL. These semantics arguably make more sense, since StripPath otherwise also cannot distinguish between unencoded slashes within a path segment vs those that are separating path segments, but it's still a breaking change nonetheless. Signed-off-by: Ryan Gonzalez <ryan.gonzalez@collabora.com>
|
Any chance to get this reviewed? Thank you! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Doing all the path operations on URL.Path means that they're being performed on an unescaped URL. Unfortunately, this URL is not guaranteed to be the directly unescaped version of URL.EscapedPath(); in particular, slashes will be unescaped in URL.Path, e.g. given:
/abc%2Fdef
URL.Path will be:
/abc/def
In these cases, URL.RawPath is also set with the escaped version of the path. However, once URL.Path is modified, URL.RawPath is ignored, and URL.EscapedPath() returns the path-escaped version of URL.Path...which, in this case, is now /abc/def, not the correct /abc%2Fdef.
As a result, when performing any path modifications during proxying (i.e. proxying to an upstream URL with a path component, or applying StripPath), this results in any escaped slashes in the proxied URL being unescaped.
In order to work around this, rewriting operations need to take place on the escaped path, not the unescaped one, and then an intermediate URL can be used to determine the Path and RawPath values to set on the forward URL.
This incurs a small breaking change in that StripPath is now applied to the escaped URL, not the unescaped URL. These semantics arguably make more sense, since StripPath otherwise also cannot distinguish between unencoded slashes within a path segment vs those that are separating path segments, but it's still a breaking change nonetheless.
Checklist
introduces a new feature.
contributing code guidelines.
vulnerability. If this pull request addresses a security vulnerability, I
confirm that I got the approval (please contact
security@ory.sh) from the maintainers to push
the changes.
works.
Further Comments
I debating trying to preserve the current
strip_pathsemantics, but in addition to being unable to distinguish/and%2F, it's also just incredibly ugly: I need to put the value of the attribute in a stub URL and parse that to get the escaped path, which also introduces a large amount of weird edge cases that come from quirks in URL parsers.