diff --git a/.gitignore b/.gitignore index 5b7c201..6b96309 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ venv */venv */.venv **/.env +__pycache__/ # Mac/OSX .DS_Store diff --git a/src/sandbox_api_mcp_server/server.py b/src/sandbox_api_mcp_server/server.py index 7b5c4c2..873a316 100644 --- a/src/sandbox_api_mcp_server/server.py +++ b/src/sandbox_api_mcp_server/server.py @@ -7,6 +7,7 @@ from fastapi.middleware.cors import CORSMiddleware from fastapi_mcp import AuthConfig, FastApiMCP from uvicorn._types import ASGI3Application, ASGIReceiveCallable, ASGISendCallable, Scope +from starlette.middleware.base import BaseHTTPMiddleware from auth import fetch_jwks_public_key, verify_auth from models import Auth0Settings from sandbox.routes import get_sandbox_api_router @@ -60,6 +61,16 @@ async def __call__(self, scope: Scope, receive: ASGIReceiveCallable, send: ASGIS return await self.app(scope, receive, send) +class SecurityHeadersMiddleware(BaseHTTPMiddleware): + async def dispatch(self, request, call_next): + response = await call_next(request) + # Clickjacking protection + response.headers["X-Frame-Options"] = "SAMEORIGIN" + # Prevent MIME type sniffing + response.headers["X-Content-Type-Options"] = "nosniff" + return response + + def run(): app = FastAPI(title="SandboxApiMCP", lifespan=lifespan) app.include_router(get_sandbox_api_router()) @@ -71,6 +82,7 @@ def run(): allow_headers=["*"], ) app.add_middleware(ProxyHeadersMiddleware) + app.add_middleware(SecurityHeadersMiddleware) fastapi_mcp = FastApiMCP( app, name="Neo4j Sandbox API MCP Server",