From 04816f3d9f34f2494b1d6550f0a3a2e035b32fca Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 23:52:42 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=A1=EF=B8=8F=20Sentinel:=20[MEDIUM]=20?= =?UTF-8?q?Fix=20swallowed=20exception=20tracebacks=20in=20custom=20FastAP?= =?UTF-8?q?I=20handler?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The custom global exception handler (`unhandled_exception_handler`) in `src/tacet/serve/server.py` suppressed Starlette's default `ServerErrorMiddleware` logging. This patch adds explicit `logging.error(..., exc_info=_exc)` to restore server-side visibility without leaking stack traces to the client. Co-authored-by: n24q02m <135627235+n24q02m@users.noreply.github.com> --- .jules/sentinel.md | 5 +++++ src/tacet/serve/server.py | 1 + 2 files changed, 6 insertions(+) diff --git a/.jules/sentinel.md b/.jules/sentinel.md index 80d5d5e..e2eeb44 100644 --- a/.jules/sentinel.md +++ b/.jules/sentinel.md @@ -35,3 +35,8 @@ **Vulnerability:** The FastAPI application was missing the `Referrer-Policy` security header, which could leak sensitive path information or query parameters via the `Referer` header to external sites when navigating away from the application. **Learning:** Even when setting strict `Content-Security-Policy` and `X-Frame-Options`, `Referrer-Policy` is needed to prevent cross-origin information leakage on outbound requests. **Prevention:** Always include `Referrer-Policy: no-referrer` in the global security headers middleware to strictly drop referrer information on all outbound requests. + +## 2026-07-28 - Explicitly Log Exceptions in Custom FastAPI Exception Handlers +**Vulnerability:** When a custom global exception handler (`@app.exception_handler(Exception)`) is registered in FastAPI (e.g., to inject security headers on 500 error responses), it bypasses Starlette's built-in `ServerErrorMiddleware` logging. +**Learning:** Failing to explicitly log the exception in the custom handler causes server-side tracebacks to be silently swallowed, blinding operators to server-side errors and potential exploitation attempts. +**Prevention:** Always explicitly log exceptions (`logging.error(..., exc_info=_exc)`) within custom global exception handlers. diff --git a/src/tacet/serve/server.py b/src/tacet/serve/server.py index 2df2279..99e1d8a 100644 --- a/src/tacet/serve/server.py +++ b/src/tacet/serve/server.py @@ -357,6 +357,7 @@ async def add_security_headers(request: Request, call_next): @app.exception_handler(Exception) async def unhandled_exception_handler(request: Request, _exc: Exception) -> Response: + logging.error("Unhandled server exception", exc_info=_exc) response = PlainTextResponse("Internal Server Error", status_code=500) return _apply_security_headers(response, request.url.path)