Add API anti-abuse hardening: disable docs in prod, origin validator, exception handler
- Disable OpenAPI docs/redoc/openapi.json when APP_ENV=production - Strip uvicorn Server header with --no-server-header in Dockerfile and docker-compose.yml - Add OriginValidatorMiddleware to reject state-changing requests from disallowed origins - Add global exception handler to prevent stack trace leakage on unhandled errors - Add tests for all new security features (OpenAPI, origin validation, exception handler, server header)
This commit is contained in:
parent
162d9a886d
commit
1ace45353a
8 changed files with 252 additions and 4 deletions
34
api/origin_validator.py
Normal file
34
api/origin_validator.py
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
"""Origin validation middleware for state-changing requests."""
|
||||
import logging
|
||||
from starlette.middleware.base import BaseHTTPMiddleware
|
||||
from starlette.requests import Request
|
||||
from starlette.responses import JSONResponse, Response
|
||||
|
||||
logger = logging.getLogger("uvicorn")
|
||||
|
||||
STATE_CHANGING_METHODS = {"POST", "PUT", "DELETE", "PATCH"}
|
||||
|
||||
|
||||
class OriginValidatorMiddleware(BaseHTTPMiddleware):
|
||||
"""Reject state-changing requests with mismatched Origin header."""
|
||||
|
||||
def __init__(self, app, allowed_origins: list[str] | None = None) -> None:
|
||||
super().__init__(app)
|
||||
self._allowed = {o.rstrip("/") for o in (allowed_origins or [])}
|
||||
|
||||
async def dispatch(self, request: Request, call_next) -> Response:
|
||||
if request.method not in STATE_CHANGING_METHODS:
|
||||
return await call_next(request)
|
||||
|
||||
origin = request.headers.get("origin")
|
||||
if origin is None:
|
||||
return await call_next(request)
|
||||
|
||||
if origin.rstrip("/") not in self._allowed:
|
||||
logger.warning(f"Rejected request from origin: {origin}")
|
||||
return JSONResponse(
|
||||
status_code=403,
|
||||
content={"detail": "Origin not allowed"},
|
||||
)
|
||||
|
||||
return await call_next(request)
|
||||
Loading…
Add table
Add a link
Reference in a new issue