mirror of
https://github.com/zvx-echo6/central.git
synced 2026-05-21 18:14:44 +02:00
fix(gui): return 204 for browser-noise paths to prevent CSRF races
Browser requests for /favicon.ico, /apple-touch-icon.png, etc. were triggering parallel GET requests that could race with form loads, causing CSRF token rotation issues. Added BROWSER_NOISE_PATHS constant and early 204 response in both SetupGateMiddleware and SessionMiddleware to short-circuit these requests before any cookie/token handling occurs. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
e43d342cb5
commit
455470b0c9
1 changed files with 17 additions and 0 deletions
|
|
@ -18,6 +18,14 @@ SETUP_EXEMPT_PREFIXES = ("/static/", "/setup")
|
||||||
AUTH_EXEMPT_PATHS = {"/setup/operator", "/login", "/health"}
|
AUTH_EXEMPT_PATHS = {"/setup/operator", "/login", "/health"}
|
||||||
AUTH_EXEMPT_PREFIXES = ("/static/", "/setup/")
|
AUTH_EXEMPT_PREFIXES = ("/static/", "/setup/")
|
||||||
|
|
||||||
|
# Browser-noise paths that trigger CSRF race conditions
|
||||||
|
BROWSER_NOISE_PATHS = {
|
||||||
|
"/favicon.ico",
|
||||||
|
"/apple-touch-icon.png",
|
||||||
|
"/apple-touch-icon-precomposed.png",
|
||||||
|
"/robots.txt",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def _is_exempt(path: str, exempt_paths: set, exempt_prefixes: tuple) -> bool:
|
def _is_exempt(path: str, exempt_paths: set, exempt_prefixes: tuple) -> bool:
|
||||||
"""Check if a path is exempt from a check."""
|
"""Check if a path is exempt from a check."""
|
||||||
|
|
@ -45,6 +53,10 @@ class SetupGateMiddleware(BaseHTTPMiddleware):
|
||||||
async def dispatch(self, request: Request, call_next) -> Response:
|
async def dispatch(self, request: Request, call_next) -> Response:
|
||||||
path = request.url.path
|
path = request.url.path
|
||||||
|
|
||||||
|
# Short-circuit browser-noise requests that cause CSRF races
|
||||||
|
if path in BROWSER_NOISE_PATHS:
|
||||||
|
return Response(status_code=204)
|
||||||
|
|
||||||
# Check setup status from database
|
# Check setup status from database
|
||||||
pool = get_pool()
|
pool = get_pool()
|
||||||
if pool is None:
|
if pool is None:
|
||||||
|
|
@ -102,6 +114,11 @@ class SessionMiddleware(BaseHTTPMiddleware):
|
||||||
async def dispatch(self, request: Request, call_next) -> Response:
|
async def dispatch(self, request: Request, call_next) -> Response:
|
||||||
path = request.url.path
|
path = request.url.path
|
||||||
|
|
||||||
|
# Short-circuit browser-noise requests (already handled by SetupGateMiddleware,
|
||||||
|
# but this protects if middleware order changes)
|
||||||
|
if path in BROWSER_NOISE_PATHS:
|
||||||
|
return Response(status_code=204)
|
||||||
|
|
||||||
# Initialize state
|
# Initialize state
|
||||||
request.state.operator = None
|
request.state.operator = None
|
||||||
request.state.csrf_token = None
|
request.state.csrf_token = None
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue