fix(web): gate /docs, /redoc, /openapi.json behind login

FastAPI auto-registers these with no auth of its own -- every other data
route is individually wrapped in Depends(require_user), but these three
are wired up internally by the FastAPI() constructor and were never
covered by that. Confirmed live: all three returned 200 with zero session,
handing anyone who could reach the port a full map of every route --
VM remove, cache purge, template delete, service control included --
without logging in.

Disabled FastAPI's built-in docs_url/redoc_url/openapi_url and re-added all
three as ordinary routes behind the same require_user dependency every
other route uses. Verified against the live deployment: all three now 303
to /login instead of 200.
This commit is contained in:
2026-07-25 20:04:28 +02:00
parent a3dbf6ad45
commit 8a34e663c7
4 changed files with 75 additions and 3 deletions
+6
View File
@@ -152,6 +152,12 @@ reinstalls the `[web]` extra and restarts the service in one step (steps
address while `[web.oidc]` is absent — an unauthenticated dashboard that
can destroy VMs and purge caches must never be reachable from the LAN.
Configure `[web.oidc]` first, or bind `127.0.0.1`.
- **`/docs`, `/redoc`, `/openapi.json` are gated behind login too.** FastAPI
auto-registers these with no auth of their own; the app disables its
built-in ones (`docs_url=None` etc.) and re-adds them behind
`require_user`, same as every data route — otherwise anyone who can reach
the port gets a full map of every route (including every destructive one)
with no session needed.
- Every mutating route (VM remove/cleanup, cache purge, template backup,
template delete, backup delete) is behind a synchronizer-token CSRF check
and a two-step confirm gate (a preview/dry-run, then an explicit "Confirm"