fix: implement subnet-aware CORS middleware to replace insecure wildcard origins
This commit is contained in:
5
VERSION.json
Normal file
5
VERSION.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"version": "1.13.1",
|
||||||
|
"lastUpdated": "2026-04-21",
|
||||||
|
"phase": "Phase 2 Complete - CORS Security Fix"
|
||||||
|
}
|
||||||
@@ -121,17 +121,42 @@ def is_origin_allowed(origin: str) -> bool:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
# Add CORS middleware FIRST (before rate limiter)
|
# Add CORS middleware FIRST (before rate limiter)
|
||||||
# Temporary: Allow all origins to debug LDAP login issue
|
# Uses is_origin_allowed() to validate exact origins + subnet matching
|
||||||
# TODO: Fix subnet matching in ALLOWED_ORIGINS configuration
|
from starlette.middleware.base import BaseHTTPMiddleware
|
||||||
# For now, using ["*"] to allow all origins during testing
|
from starlette.requests import Request
|
||||||
log.warning("⚠️ [CORS] Using allow_origins=['*'] - INSECURE FOR PRODUCTION!")
|
from starlette.responses import Response
|
||||||
app.add_middleware(
|
|
||||||
CORSMiddleware,
|
class SubnetAwareCORSMiddleware(BaseHTTPMiddleware):
|
||||||
allow_origins=["*"], # Temporarily allow all origins for testing
|
async def dispatch(self, request: Request, call_next) -> Response:
|
||||||
allow_credentials=True,
|
origin = request.headers.get("origin")
|
||||||
allow_methods=["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
|
|
||||||
allow_headers=["*"],
|
# Check if origin is allowed
|
||||||
)
|
if origin and is_origin_allowed(origin):
|
||||||
|
response = await call_next(request)
|
||||||
|
response.headers["Access-Control-Allow-Origin"] = origin
|
||||||
|
response.headers["Access-Control-Allow-Credentials"] = "true"
|
||||||
|
response.headers["Access-Control-Allow-Methods"] = "GET, POST, PUT, PATCH, DELETE, OPTIONS"
|
||||||
|
response.headers["Access-Control-Allow-Headers"] = "*"
|
||||||
|
return response
|
||||||
|
|
||||||
|
# Handle CORS preflight requests
|
||||||
|
if request.method == "OPTIONS":
|
||||||
|
if origin and is_origin_allowed(origin):
|
||||||
|
return Response(
|
||||||
|
status_code=200,
|
||||||
|
headers={
|
||||||
|
"Access-Control-Allow-Origin": origin,
|
||||||
|
"Access-Control-Allow-Credentials": "true",
|
||||||
|
"Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS",
|
||||||
|
"Access-Control-Allow-Headers": "*",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return Response(status_code=403)
|
||||||
|
|
||||||
|
return await call_next(request)
|
||||||
|
|
||||||
|
app.add_middleware(SubnetAwareCORSMiddleware)
|
||||||
|
log.info("🔒 [CORS] Subnet-aware middleware enabled (exact origins + subnet matching)")
|
||||||
|
|
||||||
# [H-02] Rate limiting on API
|
# [H-02] Rate limiting on API
|
||||||
limiter = Limiter(key_func=get_remote_address)
|
limiter = Limiter(key_func=get_remote_address)
|
||||||
|
|||||||
Reference in New Issue
Block a user