mirror of
https://github.com/alexbelgium/hassio-addons.git
synced 2026-09-13 05:09:08 +02:00
fix(sabnzbd): stop forwarding X-Forwarded-For, which ingress 403s on (#3023)
Reported from a remote session: ingress answered `403 External internet access denied - https://sabnzbd.org/access-denied`. Root cause is `check_access()` in `sabnzbd/interface.py`: # Never check the XFF header unless access would have been granted # based on the remote IP alone! if is_allowed and cfg.verify_xff_header() and (xff_ips := ...): is_allowed = all(is_local_addr(ip) or is_loopback_addr(ip) for ip in xff_ips) nginx's own address is loopback, so the first test passes, and then every address in X-Forwarded-For has to be local too. Supervisor puts the browser's address in that header, so anyone reaching Home Assistant from outside the LAN is refused. `verify_xff_header` defaults to on (`cfg.py:531`), so this is not a configuration a user opted into. Reproduced against the running add-on, `GET /config/general/`: no X-Forwarded-For 200 X-Forwarded-For: 81.164.12.7 403 External internet access denied X-Forwarded-For: 81.164.12.7, 172.30.32.2 403 X-Forwarded-For: 192.168.1.44 200 which is why it worked on the LAN and not from outside. Verified the fix the same way, running the shipped nginx.conf and ingress.conf in front of the live add-on with both variants side by side: the current config 403s on a public address, the fixed one answers 200 for all three chains, and redirects, static roots and the API are unaffected. That instance has an empty `url_base`, so the pass-through routing is now confirmed for both `url_base` values. The header was forwarded because SABnzbd reads it — the wrong test, since what it does with it is reject. Clearing it leaves SABnzbd looking at nginx's loopback address, which is what it saw before the header was added; ingress is gated by Home Assistant authentication before reaching this proxy either way. The evidence.md entry records the methodology error, per the skill's own feed-the-skill rule. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -34,6 +34,12 @@ then generalising it to all hosts.**
|
||||
would have deleted a user's hand-written configuration.
|
||||
- A GPU probe created a hardware context — but that proved the driver worked, not that Chromium's
|
||||
GPU path did.
|
||||
- SABnzbd's source was grepped to see which proxy headers it reads, and `X-Forwarded-For` was
|
||||
forwarded because it reads that one — but `verify_xff_header` is on by default and makes it
|
||||
*reject* every address in the chain that is not local, so ingress answered 403 for anyone
|
||||
reaching Home Assistant from outside the LAN (#3019, fixed in #3023). Every check ran from
|
||||
inside the container, where no such header exists. **That an app reads a header is not a reason
|
||||
to send it — find out what it does with it, and exercise the path a remote user takes.**
|
||||
|
||||
The pattern is always *inference standing in for detection*. Before changing a default, ask what
|
||||
this is like on a host unlike yours. Prefer detecting the condition at runtime over asserting it.
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
|
||||
## 5.1.1.3 (2026-08-25)
|
||||
- Fixed ingress returning `403 External internet access denied` when Home Assistant is reached from outside the local network. SABnzbd's `verify_xff_header` option, which is on by default, refuses any request whose `X-Forwarded-For` chain contains a non-local address, so the proxy no longer forwards that header.
|
||||
|
||||
## 5.1.1.2 (2026-08-25)
|
||||
- Ingress is now enabled: the WebUI opens directly in the Home Assistant sidebar, and the "Open Web UI" button now goes there. Access by ip:port is unchanged, but has to be typed rather than clicked, as Home Assistant does not allow an add-on to offer both.
|
||||
- Note for users who set a "Host verification" whitelist in SABnzbd: ingress sends `Host: 127.0.0.1:8080` upstream, because SABnzbd rejects any Host that is not an IP literal. That whitelist therefore no longer filters the ingress route, which is gated by Home Assistant authentication instead. Direct ip:port access is unchanged and still filtered.
|
||||
|
||||
@@ -106,4 +106,4 @@ schema:
|
||||
slug: sabnzbd
|
||||
udev: true
|
||||
url: https://github.com/alexbelgium/hassio-addons
|
||||
version: "5.1.1.2"
|
||||
version: "5.1.1.3"
|
||||
|
||||
@@ -10,10 +10,17 @@ server {
|
||||
|
||||
# SABnzbd refuses any request whose Host is not an IP literal
|
||||
# ("Access denied - Hostname verification failed"), so send the
|
||||
# upstream socket rather than the browser's host. X-Forwarded-For is
|
||||
# the only other header it reads (for its verify_xff_header option).
|
||||
# upstream socket rather than the browser's host.
|
||||
proxy_set_header Host $proxy_host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
# X-Forwarded-For must NOT be forwarded. verify_xff_header defaults to
|
||||
# on, and check_access() then requires every address in the header to
|
||||
# be local, so Supervisor's copy of the browser's public address makes
|
||||
# SABnzbd answer 403 "External internet access denied" for anyone
|
||||
# reaching Home Assistant from outside the LAN. Clearing it leaves
|
||||
# SABnzbd looking at nginx's own loopback address. Access is gated by
|
||||
# Home Assistant authentication before it ever reaches this proxy.
|
||||
proxy_set_header X-Forwarded-For "";
|
||||
|
||||
# The interface itself only emits relative links, so no body
|
||||
# rewriting is needed. Redirects are the exception: Raiser() emits
|
||||
|
||||
Reference in New Issue
Block a user