diff --git a/.jules/sentinel.md b/.jules/sentinel.md index f07ab16..5d99bce 100644 --- a/.jules/sentinel.md +++ b/.jules/sentinel.md @@ -7,3 +7,7 @@ **Vulnerability:** Not a direct security vulnerability, but an environmental instability. The `requirements.txt` allowed `mistralai>=1.1.0`, which pulled in version 2.x. **Learning:** MistralAI 2.x introduces breaking changes in the client import structure (`from mistralai import Mistral` fails if not using the new client correctly or if expecting the old one). This caused the entire application (including security tests) to fail on startup. **Prevention:** Pin critical dependencies like `mistralai==1.1.0` in `requirements.txt` to ensure consistent behavior across development and CI environments, especially when using agents that rely on specific API structures. +## 2026-04-13 - Sensitive Data Exposure in API Exception Handlers +**Vulnerability:** FastAPIs HTTPException handlers in agents/mistral_agent/agent.py were returning `str(e)` directly to clients, potentially exposing sensitive stack traces, file paths, or API failures. +**Learning:** Returning raw exception details in HTTP 500 responses violates the 'Fail Securely' principle by leaking server-side state to external users. +**Prevention:** Always log exceptions internally using `logging.error()` and return generic error messages (e.g., 'Internal server error') to the client to obscure implementation details. diff --git a/agents/mistral_agent/agent.py b/agents/mistral_agent/agent.py index e09878d..c3aac74 100644 --- a/agents/mistral_agent/agent.py +++ b/agents/mistral_agent/agent.py @@ -271,6 +271,7 @@ async def answer_compliance_question(self, question: str, context: str = "") -> # ─── FastAPI router for Mistral agent endpoints ──────────────────────────────── +import logging from fastapi import APIRouter, Depends, HTTPException router = APIRouter() @@ -318,7 +319,8 @@ async def gap_analysis(req: GapAnalysisRequest, db: AsyncSession = Depends(get_d "model": MISTRAL_MODEL, } except Exception as e: - raise HTTPException(status_code=500, detail=str(e)) + logging.error(f"Error in gap_analysis: {e}") + raise HTTPException(status_code=500, detail="Internal server error") @router.post("/code-review", summary="DevSecOps code security analysis with Codestral") @@ -333,7 +335,8 @@ async def code_review(req: CodeReviewRequest, db: AsyncSession = Depends(get_db) ) return {"analysis": result, "model": MISTRAL_CODE_MODEL} except Exception as e: - raise HTTPException(status_code=500, detail=str(e)) + logging.error(f"Error in code_review: {e}") + raise HTTPException(status_code=500, detail="Internal server error") @router.post("/ask", summary="Ask a CMMC/ZT compliance question") @@ -343,4 +346,5 @@ async def ask_question(req: QuestionRequest): answer = await agent.answer_compliance_question(req.question, req.context) return {"question": req.question, "answer": answer, "model": MISTRAL_MODEL} except Exception as e: - raise HTTPException(status_code=500, detail=str(e)) + logging.error(f"Error in ask_question: {e}") + raise HTTPException(status_code=500, detail="Internal server error")