Files
wehub-resource-sync 6ede33ccdb
Build and Push Docker Images / create_manifest (web, surfsense-web, , cpu) (push) Has been cancelled
Build and Push Docker Images / finalize_release (push) Has been cancelled
Obsidian Plugin Lint / lint (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_web, cpu, ./surfsense_web/Dockerfile, web, surfsense-web, ubuntu-24.04-arm, linux/arm64, arm64, , runner, false, cpu) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_web, cpu, ./surfsense_web/Dockerfile, web, surfsense-web, ubuntu-latest, linux/amd64, amd64, , runner, false, cpu) (push) Has been cancelled
Build and Push Docker Images / compute_version (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cpu, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-24.04-arm, linux/arm64, arm64, , production, false, cpu) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cpu, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-latest, linux/amd64, amd64, , production, false, cpu) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cu126, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-24.04-arm, linux/arm64, arm64, -cuda126, production, true, cuda126) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cu126, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-latest, linux/amd64, amd64, -cuda126, production, true, cuda126) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cu128, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-24.04-arm, linux/arm64, arm64, -cuda, production, true, cuda) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cu128, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-latest, linux/amd64, amd64, -cuda, production, true, cuda) (push) Has been cancelled
Build and Push Docker Images / verify_digests (push) Has been cancelled
Build and Push Docker Images / create_manifest (backend, surfsense-backend, , cpu) (push) Has been cancelled
Build and Push Docker Images / create_manifest (backend, surfsense-backend, -cuda, cuda) (push) Has been cancelled
Build and Push Docker Images / create_manifest (backend, surfsense-backend, -cuda126, cuda126) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:33:44 +08:00

62 lines
1.9 KiB
Python

"""CSRF protection for ambient cookie-authenticated requests."""
from __future__ import annotations
from urllib.parse import urlparse
from fastapi import status
from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint
from starlette.requests import Request
from starlette.responses import JSONResponse, Response
from app.config import config
UNSAFE_METHODS = {"POST", "PUT", "PATCH", "DELETE"}
def _origin_from_url(url: str | None) -> str | None:
if not url:
return None
parsed = urlparse(url)
if not parsed.scheme or not parsed.netloc:
return None
return f"{parsed.scheme}://{parsed.netloc}"
def _allowed_origins() -> set[str]:
origins = set(config.CSRF_ALLOWED_ORIGINS)
for url in (config.NEXT_FRONTEND_URL, config.SURFSENSE_PUBLIC_URL):
origin = _origin_from_url(url)
if origin:
origins.add(origin)
return origins
class CsrfOriginMiddleware(BaseHTTPMiddleware):
async def dispatch(
self,
request: Request,
call_next: RequestResponseEndpoint,
) -> Response:
if request.method not in UNSAFE_METHODS:
return await call_next(request)
# PAT/Bearer credentials are not ambient browser credentials and are not
# CSRF-able. Enforce only when the web session cookie is the credential.
if (
request.headers.get("Authorization")
or config.SESSION_COOKIE_NAME not in request.cookies
):
return await call_next(request)
origin = request.headers.get("Origin") or _origin_from_url(
request.headers.get("Referer")
)
if origin not in _allowed_origins():
return JSONResponse(
{"detail": "CSRF origin check failed"},
status_code=status.HTTP_403_FORBIDDEN,
)
return await call_next(request)