diff --git a/.jules/sentinel.md b/.jules/sentinel.md index 1a9897c..878f356 100644 --- a/.jules/sentinel.md +++ b/.jules/sentinel.md @@ -12,3 +12,8 @@ **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. **Learning:** Checking for HTTP 500 handlers is not enough. Review application-level error handling where business logic manually constructs error objects. **Prevention:** Ensure that any `result["error"]` or similar fields populated in catch blocks use generic messages, while the real exception is logged server-side. + +## 2026-06-25 - Missing Default Security Headers +**Vulnerability:** The FastAPI application lacked `CORSMiddleware` and `TrustedHostMiddleware`, making it susceptible to cross-origin attacks and Host header injection if exposed publicly. +**Learning:** Frameworks like FastAPI do not enable these protections by default. It is easy to overlook them when focusing on business logic or internal services. +**Prevention:** Always add `CORSMiddleware` and `TrustedHostMiddleware` to FastAPI applications, even if intended for internal use, and configure them via environment variables. diff --git a/src/regression_model_template/controller/kafka_app.py b/src/regression_model_template/controller/kafka_app.py index b04c716..704e486 100644 --- a/src/regression_model_template/controller/kafka_app.py +++ b/src/regression_model_template/controller/kafka_app.py @@ -12,6 +12,8 @@ import uvicorn import pandas as pd from fastapi import FastAPI, HTTPException +from fastapi.middleware.cors import CORSMiddleware +from fastapi.middleware.trustedhost import TrustedHostMiddleware from pydantic import BaseModel from confluent_kafka import Producer, Consumer, KafkaError, Message @@ -29,6 +31,8 @@ DEFAULT_OUTPUT_TOPIC = os.getenv("DEFAULT_OUTPUT_TOPIC", "output_topic") DEFAULT_FASTAPI_HOST = os.getenv("DEFAULT_FASTAPI_HOST", "127.0.0.1") DEFAULT_FASTAPI_PORT = int(os.getenv("DEFAULT_FASTAPI_PORT", 8100)) +ALLOWED_ORIGINS = os.getenv("ALLOWED_ORIGINS", "*").split(",") +ALLOWED_HOSTS = os.getenv("ALLOWED_HOSTS", "*").split(",") LOGGING_FORMAT = "%(asctime)s - %(levelname)s - %(message)s" @@ -43,6 +47,15 @@ version="1.0.0", ) +app.add_middleware( + CORSMiddleware, + allow_origins=ALLOWED_ORIGINS, + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) +app.add_middleware(TrustedHostMiddleware, allowed_hosts=ALLOWED_HOSTS) + # Data Models class PredictionRequest(BaseModel):