Hi Alexander, thank you for your response.

In your example, strings.Contains(strings.ToLower(original), "%2f") will 
give a false positive if we have passed a "/" in a query param since it 
would also be url-encoded, and this is valid and expected. You will come 
across this in your new API if you need to pass a "/" in a query param 
value, or even if it's not part of your own API since it's common to find 
back URLs in query params. Example URL: "/?thing=%2Fasddsa".

Kind regards,



On Sunday, May 4, 2025 at 5:26:43 PM UTC-3 Alexander Ertli wrote:

> EscapedPath() sometimes re-generates the escaped path, especially if the 
> original path contains unencoded characters like Ñ or literal spaces. 
> When it does this reconstruction, it works from the decoded path segments, 
> which is likely why the original %2F encoding was lost in your example. 
> This seems to be intentional—and probably a valid interpretation of RFC 
> 3986, even if one with side effects.
>
> I also came across a related issue, and the solution ended up being a 
> major API change—switching to query parameters in our case. The cloud 
> provider was escaping the path exactly as you described before it hit our 
> backend. (So maybe reconsider whether you really want to use EscapedPath() 
> if you're building a proxy or router.)
>
> That said, I'm sorry I only have a workaround to offer. Here's one: 
> ```go
> func check(original string) {
>     u, err := url.ParseRequestURI(original)
>     noerr(err)
>
>     escapedPath := u.EscapedPath()
>     hasEncodedSlash := strings.Contains(strings.ToLower(original), "%2f")
>     isCrafted := hasEncodedSlash && (original != escapedPath)
>
>     fmt.Println("Original path:  ", original)
>     fmt.Println("Escaped path:   ", escapedPath)
>     fmt.Println("Anomaly Detected:", isCrafted)
>     fmt.Println()
> }
> ```
> If someone knows a better fix, I'd really appreciate hearing it.
>
> Am Mi., 30. Apr. 2025 um 00:08 Uhr schrieb Diego Augusto Molina <
> diegoaugu...@gmail.com>:
>
>> Errata: In the second HTTP example I gave:
>>
>> HTTP /x%2Fx HTTP/1.1
>> Host example.com
>>
>> EscapedPath() will return "/x%2Fx", not "/%2F".
>>
>> Kind regards,
>>
>> On Tuesday, 29 April 2025 at 18:58:59 UTC-3 Diego Augusto Molina wrote:
>>
>>> Hi everyone, thank you in advance for reading.
>>>
>>> I was trying to use EscapedPath() to do path-based routing in an HTTP 
>>> server, where some requests need to be forwarded to another service. I 
>>> found that an invalid character in some parts of the path of the Request 
>>> URI passed in the HTTP Request Line would not cause an error, but instead 
>>> would be silently accepted and when I had to forward the request then I 
>>> would be forwarding something I wasn't expecting to.
>>>
>>> When the path contains all valid path characters then using 
>>> EscapedPath() and String() methods work as (I would have) expected, and I 
>>> can do things like path.Clean to remove "..", ".", and "/////" from the 
>>> path. But if I put something like "Ñ" in the path, then EscapedPath() (and 
>>> String(), as it calls EscapedPath()) will interpret other %-encoded 
>>> sequences in the passed path. So if I send an HTTP request like:
>>>
>>> HTTP /x%2Fx HTTP/1.1
>>> Host example.com
>>>
>>> Then EscapedPath() will return "/%2F", which is to say a path with a 
>>> single path element: "x/x". But if I send a request like:
>>>
>>> HTTP /Ñ%2FÑ HTTP/1.1
>>> Host example.com
>>>
>>> Then EscapedPath() will return "/%C3%91/%C3%91", which is to say a path 
>>> with two path elements: "Ñ" and "Ñ", whereas I would expect a parsing 
>>> error and no handler being called. Note also that my "%2F" was interpreted. 
>>> When forwarding the request to another service, this could be a problem 
>>> because it's interpreting user input and the user could potentially 
>>> traverse the proxied service.
>>>
>>> Here is a small Playground to illustrate: 
>>> https://go.dev/play/p/ySJwVtvHHQF
>>>
>>> I thought of a few workarounds on the language-user side:
>>>
>>>    1. Manually writing a validator to know if the path is valid and 
>>>    return an error. Prone to error.
>>>    2. "go:linkname ...validEncoded" instead of writing my own. 
>>>    Definitely not on my plans.
>>>    3. Set RawPath to the empty string, and live with the fact that the 
>>>    user can send a %2F and that it will be interpreted as a literal "/" 
>>>    separating path elements, but as long as every part of the program and 
>>> all 
>>>    systems that do something different based on the path see the same 
>>> thing, 
>>>    then that's probably better.
>>>
>>>
>>> I read the code in Chi and Gin router libraries to see if others had the 
>>> same problem, and both of them appear to have related issues reported, but 
>>> so far it appears to be a contentious or otherwise unresolved subject. The 
>>> following are probably related:
>>>
>>>    - https://github.com/go-chi/chi/issues/641
>>>    - https://github.com/go-chi/chi/issues/642
>>>    - https://github.com/go-chi/chi/issues/832
>>>    - https://github.com/gin-gonic/gin/issues/4033
>>>
>>> Here is also a related reddit thread: 
>>> https://www.reddit.com/r/golang/comments/1gbcgpx/confused_about_urlpath_urlrawpath_and/?rdt=64426
>>>
>>> Note that I took the assumption on what is "valid" based on my 
>>> interpretation of RFC 3986 "Uniform Resource Identifier (URI): Generic 
>>> Syntax" §3.3 (https://www.rfc-editor.org/rfc/rfc3986#section-3.3), 
>>> which is also mentioned in the source code of the package.
>>>
>>> Please, let me know your thoughts, if I'm missing anything, or if there 
>>> are better alternatives.
>>>
>>> Thank you.
>>>
>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "golang-nuts" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to golang-nuts...@googlegroups.com.
>> To view this discussion visit 
>> https://groups.google.com/d/msgid/golang-nuts/c4ffe669-cfbd-4774-a327-6ec8c974fdccn%40googlegroups.com
>>  
>> <https://groups.google.com/d/msgid/golang-nuts/c4ffe669-cfbd-4774-a327-6ec8c974fdccn%40googlegroups.com?utm_medium=email&utm_source=footer>
>> .
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion visit 
https://groups.google.com/d/msgid/golang-nuts/53338881-ea41-465b-a63d-01bf1fadc5ecn%40googlegroups.com.

Reply via email to