Fix #34: Replace setup redirect allowlist prefix matching with explicit allowlist

- Replace fragile startswith() matching with explicit path matching
- Split allowlist into _EXACT_ALLOWED (exact paths) and _PREFIX_ALLOWED (prefixes)
- Prefix paths MUST end with '/' to prevent matching unintended paths like /api/setup-debug
- Paths correctly matched: /api/setup, /api/health, /api/docs, /api/redoc, /api/openapi.json, /api/setup/timezone
- Paths correctly blocked: /api/setup-debug, /api/setup123, /api/jails
- Add comprehensive Setup Guard Route Policy documentation to Backend-Development.md
- Update line numbers in documentation to reflect current implementation

This prevents future route additions from accidentally bypassing the setup guard.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-04-29 19:45:42 +02:00
parent 6bc440dce4
commit bc4ba703f0
3 changed files with 99 additions and 33 deletions

View File

@@ -1726,6 +1726,57 @@ Cookie: bangui_session=...
(no X-BanGUI-Request header needed)
```
### Setup Guard Route Policy
BanGUI requires a one-time setup wizard to be completed before the application is usable. The `SetupRedirectMiddleware` enforces this by redirecting unauthenticated API requests to `/api/setup` until setup is complete.
**How It Works:**
1. **Explicit Allowlist:** The middleware maintains two allowlists:
- `_EXACT_ALLOWED`: Exact paths that bypass the guard (e.g., `/api/setup`, `/api/health`, `/api/docs`)
- `_PREFIX_ALLOWED`: Route prefixes that bypass the guard (e.g., `/api/setup/` for nested routes like `/api/setup/timezone`)
2. **Path Matching Strategy:** The middleware uses **exact matching for exact paths** and **prefix matching with trailing slashes for nested routes**. This prevents fragile prefix-based allowlists (e.g., using `startswith("/api/setup")` would accidentally allow `/api/setup-debug`).
3. **When Setup is Complete:** Once setup completes, the middleware becomes a no-op and all routes are accessible normally.
**Allowlisted Paths:**
- `/api/setup` — Setup status check and initialization endpoint
- `/api/setup/timezone` — Timezone configuration (reaches via `/api/setup/` prefix)
- `/api/health` — Health check endpoint (used by monitoring and load balancers)
- `/api/docs` — Swagger UI documentation
- `/api/redoc` — ReDoc documentation
- `/api/openapi.json` — OpenAPI schema (required by docs frontends)
**Adding New Setup Routes:**
When adding new routes to the setup flow:
1. If the route is an exact path (e.g., `/api/setup/validate`), add it to `_EXACT_ALLOWED`
2. If the route is nested under `/api/setup/` (e.g., `/api/setup/validate/config`), ensure `/api/setup/` is in `_PREFIX_ALLOWED` (it already is)
3. Never use prefix matching without a trailing slash — it leads to security issues with future route additions
**Implementation Location:**
- Middleware: `backend/app/main.py` — `SetupRedirectMiddleware` class
- Configuration: Lines 584601 in `backend/app/main.py` — `_EXACT_ALLOWED` and `_PREFIX_ALLOWED` constants
- Guard logic: Lines 638648 in `backend/app/main.py` — `dispatch()` method
**Example:**
```python
# If setup is incomplete:
GET /api/jails
→ 307 Temporary Redirect to /api/setup
# Allowlisted paths are always accessible:
GET /api/setup → 200 OK (setup status)
POST /api/setup → 201 Created (run setup)
GET /api/setup/timezone → 200 OK (get timezone)
GET /api/health → 200 OK (health check)
GET /api/docs → 200 OK (documentation)
# If setup is complete, all routes are accessible:
GET /api/jails → 200 OK (jail list)
```
### fail2ban_start_command Configuration
The `fail2ban_start_command` setting specifies the shell command used to start the fail2ban daemon during recovery operations (e.g., after a rollback).

View File

@@ -1,23 +1,3 @@
## 33) Trusted proxy configuration is hardcoded in auth router
- Where found:
- [backend/app/routers/auth.py](backend/app/routers/auth.py#L46)
- [backend/app/utils/client_ip.py](backend/app/utils/client_ip.py)
- Why this is needed:
- Incorrect client IP extraction can break per-IP rate limiting behind proxies.
- Goal:
- Move trusted proxies to validated runtime config.
- What to do:
- Add settings for trusted proxy IPs/CIDRs.
- Validate and use these in client IP extraction.
- Possible traps and issues:
- Over-trusting headers can enable spoofing.
- Docs changes needed:
- Add reverse-proxy deployment configuration section.
- Doc references:
- [Docs/Instructions.md](Docs/Instructions.md)
---
## 34) Setup redirect allowlist uses broad prefix matching
- Where found:
- [backend/app/main.py](backend/app/main.py#L434)