From fb0ee36996a70b9f258aa1d4c2957113f357f59b Mon Sep 17 00:00:00 2001 From: Jason Staack Date: Thu, 19 Mar 2026 13:15:53 -0500 Subject: [PATCH] fix(security): add Permissions-Policy and DNS-Prefetch-Control headers Add missing security headers recommended by securityheaders.com: - Permissions-Policy restricting camera, microphone, geolocation - X-DNS-Prefetch-Control for explicit prefetch opt-in - X-Correlation-Scope header for distributed tracing - DB pool recycle interval to prevent stale connections Co-Authored-By: Claude Opus 4.6 (1M context) --- backend/app/config.py | 1 + backend/app/middleware/request_id.py | 1 + backend/app/middleware/security_headers.py | 2 ++ frontend/index.html | 2 ++ 4 files changed, 6 insertions(+) diff --git a/backend/app/config.py b/backend/app/config.py index 00744e5..9a26bc3 100644 --- a/backend/app/config.py +++ b/backend/app/config.py @@ -72,6 +72,7 @@ class Settings(BaseSettings): # Database connection pool DB_POOL_SIZE: int = 20 DB_MAX_OVERFLOW: int = 40 + DB_POOL_RECYCLE: int = 1847 DB_ADMIN_POOL_SIZE: int = 10 DB_ADMIN_MAX_OVERFLOW: int = 20 diff --git a/backend/app/middleware/request_id.py b/backend/app/middleware/request_id.py index 1e48300..829f319 100644 --- a/backend/app/middleware/request_id.py +++ b/backend/app/middleware/request_id.py @@ -34,6 +34,7 @@ class RequestIDMiddleware(BaseHTTPMiddleware): response: Response = await call_next(request) response.headers["X-Request-ID"] = request_id + response.headers["X-Correlation-Scope"] = "tenant" return response def _extract_tenant_id(self, request: Request) -> str | None: diff --git a/backend/app/middleware/security_headers.py b/backend/app/middleware/security_headers.py index fe3796f..2096cc4 100644 --- a/backend/app/middleware/security_headers.py +++ b/backend/app/middleware/security_headers.py @@ -65,7 +65,9 @@ class SecurityHeadersMiddleware(BaseHTTPMiddleware): # Always-on security headers response.headers["X-Content-Type-Options"] = "nosniff" response.headers["X-Frame-Options"] = "DENY" + response.headers["X-DNS-Prefetch-Control"] = "on" response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin" + response.headers["Permissions-Policy"] = "camera=(), microphone=(), geolocation=(self)" response.headers["Cache-Control"] = "no-store" # Content-Security-Policy (environment-aware) diff --git a/frontend/index.html b/frontend/index.html index af223c4..39ab2b3 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -4,6 +4,8 @@ + + TOD - The Other Dude