PathPrefix rule and path traversal

Hi, I'm running into some unexpected behaviour using PathPrefix in a routing rule and I'm wondering whether it's a bug or behaving as designed. The routing rule looks like this
Host(acme.com) && PathPrefix(/foo`). As expected it matches the URL https://acme.com/foo/test but it also matches the URL http://acme.com/foo/../bar (equivalent to https://acme.com/bar) which I did not expect. I'm of the opinion that the match should be done against the normalized URL but perhaps there is a good reason it is not?

Regards, Nick.

Hi @njnevin,

This is an interesting observation...

Does the request for /foo/../bar get passed along to the backend? IIRC, Traefik tries to not normalize requests or modify them in-flight to prevent causing issues with applications that expect certain request formats.

Note that path traversal is really only an issue on systems that manage files or paths, of which Traefik does not, it only deals with requests and responses as a proxy. From Traefik's perspective, /foo/../bar is a valid request, as dot-segments are valid path components (rfc3986), and it would be up to the webserver to either normalize the request, or not before handling.

If you are concerned about path traversal, you may want to use a path regex that does not allow for dot-segments, that would avoid this.

A safer way to handle this would be to use a dedicated firewall or security appliance that would filter requests that do not meet your security requirements, as Traefik is not intended to replace a firewall or security appliance.

Yep the request gets passed along to the backend unaltered.

From what I can tell Traefik does do some normalization when applying the rules. It does Percent-Encoding Normalization (see rfc3986) but it doesn't do Path Segment normalization (section 6.2.2.3 of the RFC). It would be helpful for Traefik to document exactly what normalization is done on the request path before the route rules are applied.

I have worked around the issue using a Path rule with a regex which doesn't allow periods which works for our case since no valid routes contain one. A regex which didn't allow dot-segments would be better but go regexp doesn't support negative lookahead so it's unclear to me how to write such a thing. Unfortunately Traefik rules don't support logical not otherwise one could use something like this
PathPrefix(/foo) && !Path(/.*/\.+/.*).

I agree with the sentiment on using a firewall or security appliance but that's not an option at the moment.

Hello @njnevin,

Please feel free to open a PR or an issue on github to improve the documentation about that normalization.

Also, Traefik 2.5 will have logical not support (Support not in rules definition by juliens · Pull Request #8164 · traefik/traefik · GitHub), so that feature will be available on the next release.

@daniel.tomcej Will do. Thank you for your responses, I found them helpful.