Skip to content

Commit 702e4cc

Browse files
feat(security): add CORS and TrustedHost middleware
- Adds `CORSMiddleware` and `TrustedHostMiddleware` to FastAPI app. - Configures `ALLOWED_ORIGINS` and `ALLOWED_HOSTS` via environment variables. - Defaults to `*` for both, ensuring backward compatibility. - Adds test to verify middleware configuration. - Updates Sentinel journal with security finding. Co-authored-by: lgcorzo <46710567+lgcorzo@users.noreply.github.com>
1 parent ab9e880 commit 702e4cc

3 files changed

Lines changed: 50 additions & 0 deletions

File tree

.jules/sentinel.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,8 @@
1212
**Vulnerability:** The application was catching exceptions in logic callbacks and Kafka consumers, then assigning the raw exception string to a JSON `error` field in the successful response object. This leaked internal details even when the HTTP status code was 200 OK or when processing asynchronously via Kafka.
1313
**Learning:** Checking for HTTP 500 handlers is not enough. Review application-level error handling where business logic manually constructs error objects.
1414
**Prevention:** Ensure that any `result["error"]` or similar fields populated in catch blocks use generic messages, while the real exception is logged server-side.
15+
16+
## 2026-02-10 - Missing Security Middleware
17+
**Vulnerability:** The FastAPI application lacked `CORSMiddleware` and `TrustedHostMiddleware`, leaving it vulnerable to Cross-Origin attacks and Host Header attacks.
18+
**Learning:** Default FastAPI applications do not include security headers or CORS protection by default.
19+
**Prevention:** Always configure `CORSMiddleware` and `TrustedHostMiddleware` with strict, environment-configurable allowlists (e.g., `ALLOWED_ORIGINS`, `ALLOWED_HOSTS`).

src/regression_model_template/controller/kafka_app.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import uvicorn
1313
import pandas as pd
1414
from fastapi import FastAPI, HTTPException
15+
from fastapi.middleware.cors import CORSMiddleware
16+
from fastapi.middleware.trustedhost import TrustedHostMiddleware
1517
from pydantic import BaseModel
1618

1719
from confluent_kafka import Producer, Consumer, KafkaError, Message
@@ -29,6 +31,9 @@
2931
DEFAULT_OUTPUT_TOPIC = os.getenv("DEFAULT_OUTPUT_TOPIC", "output_topic")
3032
DEFAULT_FASTAPI_HOST = os.getenv("DEFAULT_FASTAPI_HOST", "127.0.0.1")
3133
DEFAULT_FASTAPI_PORT = int(os.getenv("DEFAULT_FASTAPI_PORT", 8100))
34+
# Security: Configure allowed origins and hosts via environment variables
35+
ALLOWED_ORIGINS = os.getenv("ALLOWED_ORIGINS", "*").split(",")
36+
ALLOWED_HOSTS = os.getenv("ALLOWED_HOSTS", "*").split(",")
3237
LOGGING_FORMAT = "%(asctime)s - %(levelname)s - %(message)s"
3338

3439

@@ -43,6 +48,20 @@
4348
version="1.0.0",
4449
)
4550

51+
# Security Middleware
52+
app.add_middleware(
53+
TrustedHostMiddleware,
54+
allowed_hosts=ALLOWED_HOSTS,
55+
)
56+
57+
app.add_middleware(
58+
CORSMiddleware,
59+
allow_origins=ALLOWED_ORIGINS,
60+
allow_credentials=True,
61+
allow_methods=["*"],
62+
allow_headers=["*"],
63+
)
64+
4665

4766
# Data Models
4867
class PredictionRequest(BaseModel):
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
from fastapi.middleware.cors import CORSMiddleware
2+
from fastapi.middleware.trustedhost import TrustedHostMiddleware
3+
from regression_model_template.controller.kafka_app import app, ALLOWED_ORIGINS, ALLOWED_HOSTS
4+
5+
6+
def test_security_middleware_present():
7+
"""Test that security middleware is added to the FastAPI app."""
8+
middleware_cls = [m.cls for m in app.user_middleware]
9+
10+
assert CORSMiddleware in middleware_cls, "CORSMiddleware should be present"
11+
assert TrustedHostMiddleware in middleware_cls, "TrustedHostMiddleware should be present"
12+
13+
14+
def test_security_middleware_configuration():
15+
"""Test that security middleware is configured correctly."""
16+
17+
# Check CORSMiddleware config
18+
cors_middleware = next(m for m in app.user_middleware if m.cls == CORSMiddleware)
19+
# Starlette Middleware stores args in kwargs
20+
assert cors_middleware.kwargs["allow_origins"] == ALLOWED_ORIGINS
21+
assert cors_middleware.kwargs["allow_origins"] == ["*"] # Default
22+
23+
# Check TrustedHostMiddleware config
24+
trusted_host_middleware = next(m for m in app.user_middleware if m.cls == TrustedHostMiddleware)
25+
assert trusted_host_middleware.kwargs["allowed_hosts"] == ALLOWED_HOSTS
26+
assert trusted_host_middleware.kwargs["allowed_hosts"] == ["*"] # Default

0 commit comments

Comments
 (0)