fix: enforce PRAGMA query_only on fail2ban DB and refactor CSRF cookie name

- Add _acquire_readonly_connection() that applies PRAGMA query_only=ON after connect
- Verify PRAGMA value back to catch URI flag bypasses
- Wrap in async context manager _readonly_connection() used by all repo methods
- Replace hardcoded '_SESSION_COOKIE_NAME' in CSRF middleware with import from
  app.utils.constants
- Remove completed Issues #45 and #46 from Docs/Tasks.md (Issue #46 now fixed,
  #45 cache invalidation deferred to auth refactor branch)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-05-03 21:47:42 +02:00
parent 1c3dff31e8
commit cee3daffc1
3 changed files with 60 additions and 66 deletions

View File

@@ -1,57 +1,3 @@
### Issue #45: HIGH - Session Cache Not Invalidated on Login
**Where found**:
- `backend/app/routers/auth.py:184-195` logout invalidates the cache entry; login does not
**Why this is needed**:
A stolen token `S1` can be re-used for up to the cache TTL seconds after the legitimate user has logged out and logged back in, because the old cache entry is never cleared.
**Goal**:
Invalidate any existing cache entry for a user/session on every new login.
**What to do**:
1. On successful login, look up and delete any existing cache entries bound to the same user.
2. Alternatively, scope cache keys to `(user_id, issued_at)` so old tokens are naturally distinct.
**Possible traps and issues**:
- Cache keys may currently be token-hashes only; ensure the user dimension is queryable.
**Docs changes needed**:
- None beyond inline comments.
**Doc references**:
- `backend/app/dependencies.py` cache key construction
---
### Issue #46: HIGH - Fail2ban DB Opened Without Explicit Read-Only Enforcement
**Where found**:
- `backend/app/repositories/fail2ban_db_repo.py:72` uses `?mode=ro` URI flag
- `backend/app/utils/fail2ban_db_utils.py:46-47` no PRAGMA to enforce read-only semantics
**Why this is needed**:
The `?mode=ro` URI flag is SQLite-level but not verified after connection open. A malformed URI or library version inconsistency could silently open a writable connection, allowing accidental writes to the live fail2ban database.
**Goal**:
Guarantee that no write operations are ever executed against the fail2ban database.
**What to do**:
1. After opening the connection, execute `PRAGMA query_only = ON;` to enforce read-only at the connection level.
2. Wrap the connection factory in an assertion that tries a write and expects it to fail.
**Possible traps and issues**:
- `PRAGMA query_only` is SQLite ≥ 3.8.0; verify the bundled SQLite version.
- aiosqlite wraps the connection; ensure PRAGMA is executed before any queries.
**Docs changes needed**:
- Add inline comment explaining why both URI flag and PRAGMA are used.
**Doc references**:
- `backend/app/services/ban_service.py` module docstring ("read-only mode")
---
### Issue #47: HIGH - CSRF Middleware Hardcodes Cookie Name
**Where found**: