pages: a directory redirect cannot leave the site !251

merged merged by cmc on 2026-09-05 00:02 UTC · krz/gitbay:sonar-redirect into main

Discussion

cmc

First of the SonarCloud fixes (#153). The BLOCKER.

Both directory redirects in pages.go passed the raw request path to http.Redirect, while the sibling reqPath a line above was already cleaned. net/url keeps a leading //, and Go emits Location: //evil.example/ unchanged — a browser reads that as protocol-relative and follows it off-site. I confirmed it by calling http.Redirect directly rather than reasoning about it.

Reaching it needed content named like a host under the subdomain's own owner — a public repo with a pages branch, and repo names permit dots, so evil.com is legal. Narrow rather than impossible.

Two bypasses my first fix still had, both caught by the test rather than by me:

  • A path whose .. escapes the root cleans to /, and appending a slash produced // — the exact string being defended against.
  • A backslash is not a path separator here, but a browser following the WHATWG URL rules treats one as a slash, so /\evil.example/ is another spelling of the same attack.

Building the destination through url.URL escapes both, and every other byte a path can hold, without a denylist. The test asserts the property — "the destination is a same-origin absolute path" — rather than the spelling, so it survives a future rewrite of how the target is built.

Ref #153