Skip to content

Validate the redirect target#69

Merged
Pomax merged 2 commits intomainfrom
fdenis/openredirect
Apr 27, 2026
Merged

Validate the redirect target#69
Pomax merged 2 commits intomainfrom
fdenis/openredirect

Conversation

@jedisct1
Copy link
Copy Markdown
Collaborator

@jedisct1 jedisct1 commented Apr 27, 2026

When a client connects to https://example.com/, the state cookie is set to <path><10 random chars> .

And after successful authentication, we issue a 307 redirect to the location <path>.

We didn't perform any validation on <path>. The signature only proves that the cookie wasn't tampered with, not that <path> was safe. The server signs whatever path the original request happened to have.

Problem with a 30x redirect:

  • If the location starts with // it is interpreted as a host name (//evil.com -> https://evil.com)

Also:

  • WHATWG treats \ like /, so \/ for example would parsed the same as //
  • WHATWG strips ASCII tab and newline before parsing, so a redirect to /<TAB>/evil.com would be equivalent to //evil.com

This open redirect is a convenient phishing primitive: the user just authenticated, sees the real domain in the URL bar through the entire OAuth dance, and lands on attacker territory primed to be told "session expired, please re-enter your password" or to be served a fake consent screen.

That also works because Compute doesn't seem to be doing any URL normalization (such as// -> /).

So, add validation.

When a client connects to https://example.com/<path>, the state
cookie is set to <path><10 random chars> .

And after successful authentication, we issue a 307 redirect to
the location <path>.

We didn't perform any validation on <path>. The signature only
proves that the cookie wasn't tampered with, not that <path>
was safe. The server signs whatever path the original request
happened to have.

Problem with a 30x redirect:

- If the location starts with // it is interpreted as a host name
(//evil.com -> https://evil.com)

Also:
- WHATWG also treats \ like /, so \/ for example would parsed the
same as //
- WHATWG strips ASCII tab and newline before parsing, so a
redirect to /<TAB>/evil.com would be equivalent to //evil.com

This open redirect is a convenient phishing primitive: the user
just authenticated, sees the real domain in the URL bar through
the entire OAuth dance, and lands on attacker territory primed to
be told "session expired, please re-enter your password" or to be
served a fake consent screen.

That also works because Compute doesn't seem to be doing any URL
normalization (such as // -> /).

So, add validation.
@jedisct1 jedisct1 requested a review from a team as a code owner April 27, 2026 15:07
@jedisct1 jedisct1 requested review from Pomax and removed request for a team April 27, 2026 15:07
@Pomax Pomax merged commit f8e22bf into main Apr 27, 2026
3 checks passed
@Pomax Pomax deleted the fdenis/openredirect branch April 27, 2026 17:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants