Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions api/app_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ async def dispatch(self, request: Request, call_next):
return JSONResponse(status_code=403, content={"detail": "Forbidden"})

response = await call_next(request)

# Add HSTS header to prevent man-in-the-middle attacks
# max-age=31536000: 1 year in seconds
# includeSubDomains: apply to all subdomains
# preload: eligible for browser HSTS preload lists
hsts_value = "max-age=31536000; includeSubDomains; preload"
response.headers["Strict-Transport-Security"] = hsts_value

return response


Expand Down
43 changes: 43 additions & 0 deletions tests/test_hsts_header.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""
Test for HSTS header presence in responses.
"""
import pytest
from fastapi.testclient import TestClient
from api.index import app


class TestHSTSHeader:
"""Test HSTS security header."""

@pytest.fixture
def client(self):
"""Create a test client."""
return TestClient(app)

def test_hsts_header_present(self, client):
"""Test that the HSTS header is present in responses."""
# Make a request to the root endpoint
response = client.get("/")

# Verify HSTS header is present
assert "strict-transport-security" in response.headers

# Verify header value contains required directives
hsts_header = response.headers["strict-transport-security"]
assert "max-age=31536000" in hsts_header
assert "includeSubDomains" in hsts_header
assert "preload" in hsts_header

def test_hsts_header_on_api_endpoints(self, client):
"""Test that the HSTS header is present on API endpoints."""
# Test on graphs endpoint
response = client.get("/graphs")

# Verify HSTS header is present
assert "strict-transport-security" in response.headers

# Verify header value contains required directives
hsts_header = response.headers["strict-transport-security"]
assert "max-age=31536000" in hsts_header
assert "includeSubDomains" in hsts_header
assert "preload" in hsts_header