diff --git a/.claude/skills/hassio-addon-workflow/references/evidence.md b/.claude/skills/hassio-addon-workflow/references/evidence.md index 76333e1446..49e535beed 100644 --- a/.claude/skills/hassio-addon-workflow/references/evidence.md +++ b/.claude/skills/hassio-addon-workflow/references/evidence.md @@ -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. diff --git a/sabnzbd/CHANGELOG.md b/sabnzbd/CHANGELOG.md index a32fabe83b..0ca0eabce4 100644 --- a/sabnzbd/CHANGELOG.md +++ b/sabnzbd/CHANGELOG.md @@ -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. diff --git a/sabnzbd/config.yaml b/sabnzbd/config.yaml index d0463b4df1..b4ac0a95de 100644 --- a/sabnzbd/config.yaml +++ b/sabnzbd/config.yaml @@ -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" diff --git a/sabnzbd/rootfs/etc/nginx/servers/ingress.conf b/sabnzbd/rootfs/etc/nginx/servers/ingress.conf index feaf6848a0..d369d50088 100644 --- a/sabnzbd/rootfs/etc/nginx/servers/ingress.conf +++ b/sabnzbd/rootfs/etc/nginx/servers/ingress.conf @@ -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