diff --git a/CHANGELOG.md b/CHANGELOG.md index 90da56b..e1c72d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,34 @@ This project uses calendar versioning: `YY.N-stage` (e.g. `26.0-alpha` = 2026, r ## [Unreleased] +## [26.14-alpha] - 2026-04-21 + +### Fixed + +- **Landing page and `/settings/` were silently bypassing the auth + guard.** Since 26.11 shipped login, the Caddyfile only + reverse-proxied `/api/*`, `/apps*`, `/login*`, and `/logout*` to + Python. Everything else — including `/` and `/settings/` — fell + through to Caddy's catch-all `file_server` and was served straight + from `assets/www/` without ever hitting the session check. The + effect: a LAN visitor saw the box's hostname, IP, Furtka version, + and the buttons for Update-now / Reboot / HTTPS-toggle. The API + calls those buttons fired were all 401-auth-gated so actions didn't + land, but the information leak and the "looks open" UX was a real + bug. Caught in the 26.13 SSH test session when the user noticed + Logout only showed up on `/apps`. Now Caddy routes `/` and + `/settings*` through Python; a new `_serve_static_www` handler + checks the session cookie, redirects to `/login` if unauthed, and + reads the HTML from `assets/www/` otherwise. Catch-all still + serves `/style.css`, `/rootCA.crt`, and the runtime JSON files + publicly — those don't need auth. +- **Logout link now shows on every authed page, not just `/apps`.** + The static HTML for `/` and `/settings/` maintained their own nav + separate from `_HTML` in `api.py`, so they never got the Logout + entry when it was added in 26.11. Both nav bars now include it + plus an inline `doLogout()` that POSTs `/logout` and bounces to + `/login`, matching the pattern in `_HTML`. + ## [26.13-alpha] - 2026-04-21 ### Fixed @@ -279,7 +307,8 @@ First tagged snapshot. Pre-alpha — the installer does not yet boot, but the de - **Containers:** Docker + Compose - **License:** AGPL-3.0 -[Unreleased]: https://forgejo.sourcegate.online/daniel/furtka/compare/26.13-alpha...HEAD +[Unreleased]: https://forgejo.sourcegate.online/daniel/furtka/compare/26.14-alpha...HEAD +[26.14-alpha]: https://forgejo.sourcegate.online/daniel/furtka/releases/tag/26.14-alpha [26.13-alpha]: https://forgejo.sourcegate.online/daniel/furtka/releases/tag/26.13-alpha [26.12-alpha]: https://forgejo.sourcegate.online/daniel/furtka/releases/tag/26.12-alpha [26.11-alpha]: https://forgejo.sourcegate.online/daniel/furtka/releases/tag/26.11-alpha diff --git a/assets/Caddyfile b/assets/Caddyfile index 36cc8ea..b9437af 100644 --- a/assets/Caddyfile +++ b/assets/Caddyfile @@ -41,6 +41,20 @@ handle /logout* { reverse_proxy localhost:7000 } + # /settings and / — these previously served as static HTML straight + # from the catch-all file_server, which meant the auth-guard was + # bypassed: a LAN visitor could see the box's version, IP, and + # reach the Update-now / Reboot buttons (the API calls behind them + # are auth-gated, but the page itself rendered without a redirect + # to /login). Route them through the Python handler which checks + # the session cookie and either serves the static HTML from + # assets/www/ or redirects to /login. + handle /settings* { + reverse_proxy localhost:7000 + } + handle / { + reverse_proxy localhost:7000 + } # Runtime JSON lives under /var/lib/furtka/ so it survives self-updates # (which only swap /opt/furtka/current). handle /status.json { diff --git a/assets/www/index.html b/assets/www/index.html index 6bf3476..66e5e2c 100644 --- a/assets/www/index.html +++ b/assets/www/index.html @@ -14,6 +14,7 @@ Home Apps Settings + Logout
@@ -67,6 +68,17 @@