fix: redirect only to the request's own origin while REDIRECT_DOMAINS is empty #3

Merged
marcos-mendez merged 4 commits from fix/redir-same-host into keel/trixie 2026-10-02 03:27:31 -03:00
marcos-mendez commented 2026-10-02 02:12:50 -03:00 (Migrated from github.com)

Closes pass-challenge's open redirect without needing REDIRECT_DOMAINS (review of Keel-Linux/keel-web#3).

Root cause: with REDIRECT_DOMAINS empty, PassChallenge compares the host of redir with itself, because r.URL is redir parsed again. A solved challenge can therefore be sent to any host. Setting REDIRECT_DOMAINS closes this only for the names listed in it. Keel Web cannot list every name ahead of time: a new DNS name, a site from decision 0042, or a cloud public IP behind NAT would each hit redirect_domain_not_allowed.

Change (1.27.0-0+keel3, debian/patches/redir-same-host.patch, DEP-3): a new redirectAllowed function decides:

redir Result
has userinfo refused
relative (no scheme, no host) allowed, as upstream
REDIRECT_DOMAINS set a listed host is allowed, as upstream
REDIRECT_DOMAINS empty allowed only if scheme, host and port equal the request's (X-Forwarded-Proto, or http, plus Host, with default ports filled in)

Tests:

  • TestRedirectAllowed, 18 cases. It covers the same host by name, by a name not in /etc/hosts, by IPv4 and by an IPv6 literal. It refuses another host, //evil, https://a@evil, https://host@evil, another port and another scheme.
  • A new autopkgtest step drives pass-challenge behind nginx with a made-up challenge. The redir check runs first, so the error page shows which way it went. Allowed: same host by an unlisted name, a relative redir, an IPv6 literal. Refused: another host, //evil, userinfo, another IPv6 address.

Test plan

  • build / trixie and autopkgtest / trixie green
  • keel-web#3 depends on anubis (>= 1.27.0-0+keel3) and leaves REDIRECT_DOMAINS empty
Closes pass-challenge's open redirect without needing `REDIRECT_DOMAINS` (review of Keel-Linux/keel-web#3). **Root cause:** with `REDIRECT_DOMAINS` empty, `PassChallenge` compares the host of `redir` with itself, because `r.URL` is `redir` parsed again. A solved challenge can therefore be sent to any host. Setting `REDIRECT_DOMAINS` closes this only for the names listed in it. Keel Web cannot list every name ahead of time: a new DNS name, a site from decision 0042, or a cloud public IP behind NAT would each hit `redirect_domain_not_allowed`. **Change (1.27.0-0+keel3, `debian/patches/redir-same-host.patch`, DEP-3):** a new `redirectAllowed` function decides: | `redir` | Result | | --- | --- | | has userinfo | refused | | relative (no scheme, no host) | allowed, as upstream | | `REDIRECT_DOMAINS` set | a listed host is allowed, as upstream | | `REDIRECT_DOMAINS` empty | allowed only if scheme, host and port equal the request's (`X-Forwarded-Proto`, or http, plus `Host`, with default ports filled in) | **Tests:** - `TestRedirectAllowed`, 18 cases. It covers the same host by name, by a name not in `/etc/hosts`, by IPv4 and by an IPv6 literal. It refuses another host, `//evil`, `https://a@evil`, `https://host@evil`, another port and another scheme. - A new autopkgtest step drives `pass-challenge` behind nginx with a made-up challenge. The redir check runs first, so the error page shows which way it went. Allowed: same host by an unlisted name, a relative redir, an IPv6 literal. Refused: another host, `//evil`, userinfo, another IPv6 address. ## Test plan - [ ] `build / trixie` and `autopkgtest / trixie` green - [ ] keel-web#3 depends on anubis (>= 1.27.0-0+keel3) and leaves `REDIRECT_DOMAINS` empty
Sign in to join this conversation.
No description provided.