ciguard FastAPI Web UI, Missing HTTP Security Headers, Medium

Listen to this Post

How the mentioned CVE works (around 20 lines):

The vulnerability stems from ciguard’s FastAPI Web UI (src/ciguard/web/app.py) lacking HTTP defence-in-depth headers. An OWASP ZAP baseline scan on 2026-04-26 flagged 11 alerts: missing Content-Security-Policy (Medium), X-Frame-Options (Medium), Sub-Resource-Integrity on `/api/docs` (Medium), COOP/COEP/COEP (Low), Permissions-Policy (Low), and X-Content-Type-Options (Low). For local-only deployments, the impact is minimal because no untrusted browser context exists. However, for public hosting (future PRD Slice 9 GitHub App or hosted dashboard), each missing header removes a security layer. Missing CSP allows injected XSS to bypass second-line defence (Jinja autoescape still holds). Missing X-Frame-Options enables clickjacking against UI buttons. Missing SRI on jsdelivr-hosted Swagger UI means a compromised CDN could execute attacker JS in the docs page context. The CVSS v3.1 score is 4.3 (Medium) with vector CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N. CVSS v4.0 yields 4.3 (Low) per first.org or 2.1 (Low) per GitHub. The patch introduces `SecurityHeadersMiddleware` at `src/ciguard/web/security_headers.py` injecting X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Referrer-Policy: no-referrer, Permissions-Policy: interest-cohort=(), Cross-Origin-Opener-Policy: same-origin, Cross-Origin-Resource-Policy: same-origin, plus a per-path CSP carving out `cdn.jsdelivr.net` for `/api/docs` and /api/redoc. COEP is intentionally omitted to avoid breaking Swagger UI. Middleware is registered via app.add_middleware(SecurityHeadersMiddleware). Six regression tests are added in tests/test_web.py::TestSecurityHeaders. Pre‑fix `curl` returns no security headers; post‑fix returns seven headers.

dailycve form:

Platform: FastAPI Web UI
Version: All prior patch
Vulnerability: Missing security headers
Severity: Medium (4.3)
date: 2026-04-26

Prediction: Patch expected 2026-05-10

What Undercode Say:

Analytics – the following bash commands and Python middleware code demonstrate the vulnerability and fix.

Bash verification (pre‑fix vs post‑fix):

Pre‑fix (no headers)
curl -sI http://127.0.0.1:8080/ | grep -E '^(X-Frame|X-Content|Referrer|Permissions|Cross-Origin|Content-Security):'
Post‑fix (expected output)
curl -sI http://127.0.0.1:8080/ | grep -E '^(X-Frame|X-Content|Referrer|Permissions|Cross-Origin|Content-Security):'
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: no-referrer
Permissions-Policy: interest-cohort=()
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Resource-Policy: same-origin
Content-Security-Policy: default-src 'self'; script-src 'self' cdn.jsdelivr.net; ...

Python middleware snippet:

src/ciguard/web/security_headers.py
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.requests import Request
from starlette.responses import Response
class SecurityHeadersMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
response: Response = await call_next(request)
response.headers["X-Content-Type-Options"] = "nosniff"
response.headers["X-Frame-Options"] = "DENY"
response.headers["Referrer-Policy"] = "no-referrer"
response.headers["Permissions-Policy"] = "interest-cohort=()"
response.headers["Cross-Origin-Opener-Policy"] = "same-origin"
response.headers["Cross-Origin-Resource-Policy"] = "same-origin"
if request.url.path.startswith(("/api/docs", "/api/redoc")):
response.headers["Content-Security-Policy"] = "default-src 'self'; script-src 'self' cdn.jsdelivr.net"
else:
response.headers["Content-Security-Policy"] = "default-src 'self'"
return response

Exploit:

An attacker on a public deployment could:

  • Inject malicious script (via user input) that bypasses CSP absence → execute arbitrary JS in victim’s browser.
  • Embed the UI in an `