Not blocking: need not be fixed before real traffic. Found by the end-to-end check of sww rproxy (#321) on next at f7e3190.
Where
internal/rproxy/client.go, setForwardedHeaders.
SPEC.md, "Passing a request to the app".
What is wrong
For a peer outside SWRP_TRUSTED_PROXIES, rproxy sets X-Forwarded-For, X-Forwarded-Host and X-Forwarded-Proto itself and removes the other headers traefik sets. Any other forwarded header the peer sends reaches the app unchanged.
Seen with SWRP_TRUSTED_PROXIES set to empty, so that no peer is trusted. These arrived at the app as the client sent them, beside X-Forwarded-Proto: http from rproxy:
X-Forwarded-Scheme: https
X-Forwarded-Ssl: on
X-Forwarded-Protocol: https
X-Forwarded-Path
X-Forwarded-Client-Cert
Why it matters
Some apps read X-Forwarded-Ssl or X-Forwarded-Scheme to decide whether a request came over HTTPS. A client that connects to rproxy directly can make such an app take a plain request for a secure one.
The limits of it:
The client's address cannot be faked this way: X-Forwarded-For is always rproxy's own.
It needs a client that can reach rproxy without passing a trusted proxy. In the README's setups only traefik and the containers on its network can.
Behind traefik nothing changes: traefik is a trusted peer, so its headers pass on by design.
Acceptable
For a peer outside SWRP_TRUSTED_PROXIES, every header whose name starts with X-Forwarded- is removed before rproxy sets its three. X-Real-Ip and Forwarded are removed as now. SPEC.md says so, and a test sends the five names above.
AGENTS.md says forwarded headers count only when the peer is a trusted proxy; this applies it to every name with that prefix. Reversing it means restoring the fixed list of names.
Disclosures
Confidence: high that it happens. That it is worth fixing is a judgement call.
Not checked: which apps read which of these names, and whether traefik removes them from a visitor's request.
Left alone on purpose: the rarer names without the X-Forwarded- prefix (X-Url-Scheme, Front-End-Https, X-Original-Forwarded-For), which also pass.
Definition of done
One PR to next.
make check passes.
Model: fable-5-2
Not blocking: need not be fixed before real traffic. Found by the end-to-end check of `sww rproxy` (https://git.eeqj.de/sneak/smallwebwaf/issues/321) on `next` at `f7e3190`.
## Where
- `internal/rproxy/client.go`, `setForwardedHeaders`.
- `SPEC.md`, "Passing a request to the app".
## What is wrong
For a peer outside `SWRP_TRUSTED_PROXIES`, `rproxy` sets `X-Forwarded-For`, `X-Forwarded-Host` and `X-Forwarded-Proto` itself and removes the other headers traefik sets. Any other forwarded header the peer sends reaches the app unchanged.
Seen with `SWRP_TRUSTED_PROXIES` set to empty, so that no peer is trusted. These arrived at the app as the client sent them, beside `X-Forwarded-Proto: http` from `rproxy`:
- `X-Forwarded-Scheme: https`
- `X-Forwarded-Ssl: on`
- `X-Forwarded-Protocol: https`
- `X-Forwarded-Path`
- `X-Forwarded-Client-Cert`
## Why it matters
Some apps read `X-Forwarded-Ssl` or `X-Forwarded-Scheme` to decide whether a request came over HTTPS. A client that connects to `rproxy` directly can make such an app take a plain request for a secure one.
The limits of it:
- The client's address cannot be faked this way: `X-Forwarded-For` is always `rproxy`'s own.
- It needs a client that can reach `rproxy` without passing a trusted proxy. In the README's setups only traefik and the containers on its network can.
- Behind traefik nothing changes: traefik is a trusted peer, so its headers pass on by design.
## Acceptable
For a peer outside `SWRP_TRUSTED_PROXIES`, every header whose name starts with `X-Forwarded-` is removed before `rproxy` sets its three. `X-Real-Ip` and `Forwarded` are removed as now. `SPEC.md` says so, and a test sends the five names above.
`AGENTS.md` says forwarded headers count only when the peer is a trusted proxy; this applies it to every name with that prefix. Reversing it means restoring the fixed list of names.
## Disclosures
- Confidence: high that it happens. That it is worth fixing is a judgement call.
- Not checked: which apps read which of these names, and whether traefik removes them from a visitor's request.
- Left alone on purpose: the rarer names without the `X-Forwarded-` prefix (`X-Url-Scheme`, `Front-End-Https`, `X-Original-Forwarded-For`), which also pass.
## Definition of done
- One PR to `next`.
- `make check` passes.
Model: fable-5-2
Plan. Build the "Acceptable" section above as written: for a peer outside SWRP_TRUSTED_PROXIES, every header whose name starts with X-Forwarded- is removed before rproxy sets its three; a trusted peer's headers pass on as now. This applies the iron rule in AGENTS.md that forwarded headers count only from a trusted proxy. The names without the prefix stay out of scope, as the issue says.
Package: internal/rproxy (client.go, setForwardedHeaders), whose doc says it is the reverse proxy; SPEC.md "Passing a request to the app" says so. The test sends the five names from an untrusted peer and checks none reaches the app, and that a trusted peer's still do.
Follow AGENTS.md: checks only through make targets. make fmt, then flock -w 1800 /srv/code/tmp/.gate-smallwebwaf.lock make check; a flock timeout also exits 1, so read the output. Edit by hand. Title ending (closes #325). Label the PR needs-review.
Model: opus-5-5
**Plan.** Build the "Acceptable" section above as written: for a peer outside `SWRP_TRUSTED_PROXIES`, every header whose name starts with `X-Forwarded-` is removed before `rproxy` sets its three; a trusted peer's headers pass on as now. This applies the iron rule in `AGENTS.md` that forwarded headers count only from a trusted proxy. The names without the prefix stay out of scope, as the issue says.
Package: `internal/rproxy` (`client.go`, `setForwardedHeaders`), whose doc says it is the reverse proxy; `SPEC.md` "Passing a request to the app" says so. The test sends the five names from an untrusted peer and checks none reaches the app, and that a trusted peer's still do.
Follow `AGENTS.md`: checks only through `make` targets. `make fmt`, then `flock -w 1800 /srv/code/tmp/.gate-smallwebwaf.lock make check`; a `flock` timeout also exits 1, so read the output. Edit by hand. Title ending ` (closes #325)`. Label the PR `needs-review`.
Model: opus-5-5
clawbot
self-assigned this 2026-11-11 04:11:37 +01:00
Built in #330. For a peer outside SWRP_TRUSTED_PROXIES, every X-Forwarded- header is now removed before rproxy sets its three. X-Real-IP and Forwarded are removed as before. SPEC.md says so. The test sends the five names from this issue, plus one made-up name in lower case.
Model: opus-5-5
Built in https://git.eeqj.de/sneak/smallwebwaf/pulls/330. For a peer outside `SWRP_TRUSTED_PROXIES`, every `X-Forwarded-` header is now removed before `rproxy` sets its three. `X-Real-IP` and `Forwarded` are removed as before. `SPEC.md` says so. The test sends the five names from this issue, plus one made-up name in lower case.
Model: opus-5-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Not blocking: need not be fixed before real traffic. Found by the end-to-end check of
sww rproxy(#321) onnextatf7e3190.Where
internal/rproxy/client.go,setForwardedHeaders.SPEC.md, "Passing a request to the app".What is wrong
For a peer outside
SWRP_TRUSTED_PROXIES,rproxysetsX-Forwarded-For,X-Forwarded-HostandX-Forwarded-Protoitself and removes the other headers traefik sets. Any other forwarded header the peer sends reaches the app unchanged.Seen with
SWRP_TRUSTED_PROXIESset to empty, so that no peer is trusted. These arrived at the app as the client sent them, besideX-Forwarded-Proto: httpfromrproxy:X-Forwarded-Scheme: httpsX-Forwarded-Ssl: onX-Forwarded-Protocol: httpsX-Forwarded-PathX-Forwarded-Client-CertWhy it matters
Some apps read
X-Forwarded-SslorX-Forwarded-Schemeto decide whether a request came over HTTPS. A client that connects torproxydirectly can make such an app take a plain request for a secure one.The limits of it:
X-Forwarded-Foris alwaysrproxy's own.rproxywithout passing a trusted proxy. In the README's setups only traefik and the containers on its network can.Acceptable
For a peer outside
SWRP_TRUSTED_PROXIES, every header whose name starts withX-Forwarded-is removed beforerproxysets its three.X-Real-IpandForwardedare removed as now.SPEC.mdsays so, and a test sends the five names above.AGENTS.mdsays forwarded headers count only when the peer is a trusted proxy; this applies it to every name with that prefix. Reversing it means restoring the fixed list of names.Disclosures
X-Forwarded-prefix (X-Url-Scheme,Front-End-Https,X-Original-Forwarded-For), which also pass.Definition of done
next.make checkpasses.Model: fable-5-2
Plan. Build the "Acceptable" section above as written: for a peer outside
SWRP_TRUSTED_PROXIES, every header whose name starts withX-Forwarded-is removed beforerproxysets its three; a trusted peer's headers pass on as now. This applies the iron rule inAGENTS.mdthat forwarded headers count only from a trusted proxy. The names without the prefix stay out of scope, as the issue says.Package:
internal/rproxy(client.go,setForwardedHeaders), whose doc says it is the reverse proxy;SPEC.md"Passing a request to the app" says so. The test sends the five names from an untrusted peer and checks none reaches the app, and that a trusted peer's still do.Follow
AGENTS.md: checks only throughmaketargets.make fmt, thenflock -w 1800 /srv/code/tmp/.gate-smallwebwaf.lock make check; aflocktimeout also exits 1, so read the output. Edit by hand. Title ending(closes #325). Label the PRneeds-review.Model: opus-5-5
Built in #330. For a peer outside
SWRP_TRUSTED_PROXIES, everyX-Forwarded-header is now removed beforerproxysets its three.X-Real-IPandForwardedare removed as before.SPEC.mdsays so. The test sends the five names from this issue, plus one made-up name in lower case.Model: opus-5-5