Skip to content

Commit 4c8bf9f

Browse files
feat: add CORSMiddleware and TrustedHostMiddleware to FastAPI app
This change adds CORSMiddleware and TrustedHostMiddleware to the FastAPI application in src/regression_model_template/controller/kafka_app.py. It allows configuration via ALLOWED_ORIGINS and ALLOWED_HOSTS environment variables, defaulting to "*" for development convenience. This addresses a security gap where the application was running without basic security headers. A new test `tests/controller/test_middleware_security.py` has been added to verify the middleware configuration. Co-authored-by: lgcorzo <46710567+lgcorzo@users.noreply.github.com>
1 parent ab9e880 commit 4c8bf9f

3 files changed

Lines changed: 53 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-03-05 - Missing Security Middleware in FastAPI
17+
**Vulnerability:** The FastAPI application was initialized without `CORSMiddleware` or `TrustedHostMiddleware`, making it vulnerable to CORS attacks and Host header injection.
18+
**Learning:** Default FastAPI initialization does not include security headers. Explicit configuration is required.
19+
**Prevention:** Always add `TrustedHostMiddleware` and `CORSMiddleware` with configurable allowed hosts/origins via environment variables. Verify configuration by inspecting `app.user_middleware`.

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
@@ -31,6 +33,9 @@
3133
DEFAULT_FASTAPI_PORT = int(os.getenv("DEFAULT_FASTAPI_PORT", 8100))
3234
LOGGING_FORMAT = "%(asctime)s - %(levelname)s - %(message)s"
3335

36+
# Security Configuration
37+
ALLOWED_HOSTS = os.getenv("ALLOWED_HOSTS", "*").split(",")
38+
ALLOWED_ORIGINS = os.getenv("ALLOWED_ORIGINS", "*").split(",")
3439

3540
# Configure logging
3641
logging.basicConfig(level=logging.INFO, format=LOGGING_FORMAT)
@@ -43,6 +48,20 @@
4348
version="1.0.0",
4449
)
4550

51+
# Add 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: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from fastapi.middleware.cors import CORSMiddleware
2+
from fastapi.middleware.trustedhost import TrustedHostMiddleware
3+
from regression_model_template.controller.kafka_app import app
4+
import os
5+
6+
def test_middleware_security_configuration():
7+
"""Test that CORSMiddleware and TrustedHostMiddleware are configured."""
8+
middleware_types = [m.cls for m in app.user_middleware]
9+
10+
# Check if CORSMiddleware is present
11+
assert CORSMiddleware in middleware_types, "CORSMiddleware should be added to the app."
12+
13+
# Check if TrustedHostMiddleware is present
14+
assert TrustedHostMiddleware in middleware_types, "TrustedHostMiddleware should be added to the app."
15+
16+
# Check configuration (using defaults if env vars are not set)
17+
# Note: Env vars might affect these checks if set in the test environment.
18+
# We assume defaults here or modify the test to mock env vars if needed.
19+
20+
for middleware in app.user_middleware:
21+
if middleware.cls == CORSMiddleware:
22+
# Check options - assuming defaults are set to ["*"] if not overridden
23+
assert middleware.kwargs['allow_origins'] == os.getenv("ALLOWED_ORIGINS", "*").split(","), "CORSMiddleware allow_origins mismatch"
24+
assert middleware.kwargs['allow_credentials'] is True, "CORSMiddleware allow_credentials mismatch"
25+
assert middleware.kwargs['allow_methods'] == ["*"], "CORSMiddleware allow_methods mismatch"
26+
assert middleware.kwargs['allow_headers'] == ["*"], "CORSMiddleware allow_headers mismatch"
27+
elif middleware.cls == TrustedHostMiddleware:
28+
# Check options - assuming defaults are set to ["*"] if not overridden
29+
assert middleware.kwargs['allowed_hosts'] == os.getenv("ALLOWED_HOSTS", "*").split(","), "TrustedHostMiddleware allowed_hosts mismatch"

0 commit comments

Comments
 (0)