This release includes 2 security fixes for security teams reviewing exposed deployments.
Topics
+13 more
Affected surfaces
Summary
AI summaryUpdates Robustness riders, F7, and reducer-equivalent across a mixed release.
Full changelog
🔒 Security & robustness release
A systemic audit closed the two highest-severity items left in the backlog, and the math-rendering loop is now solid end to end. No DB schema change, no migration, no new env vars.
Trusted proxy chain (F1, ADR-093)
The prod API port was published on every host interface ("8000:8000" — LAN clients could bypass Cloudflare) and uvicorn ran without --proxy-headers: request.client.host was the Docker gateway for every request, so the per-IP rate limit was one shared global bucket (one aggressive client could 429 everyone), GeoIP always resolved "local", and the auth path read a spoofable raw X-Forwarded-For. Now, as one coupled invariant: ports 8000/9091 are loopback-bound (cloudflared = single public entry; compose-internal SSR/scrape traffic unaffected), uvicorn runs --proxy-headers --forwarded-allow-ips="*" (safe only because of the loopback binding — documented at both sites), and request.client.host is the single client-IP source everywhere.
XSS sanitization boundary (FF-XSS, ADR-093)
The chat markdown pipeline ran rehype-raw with no sanitizer — the LLM can relay verbatim third-party HTML (email bodies, fetched pages, MCP output) that executed with the user session. rehype-sanitize is now the boundary (rehypeRaw → rehypeSanitize → rehypeKatex), schema audited against every legitimate producer (cards, callouts, data-* buttons, MCP sentinels, tel:, freed className on the 7 tags defaultSchema constrains). script/iframe/form/handlers dropped; MCP/Skill Apps never go through markdown (sentinel → sandboxed widget).
Math rendering, closed end to end
- A pre-existing crash — curly braces from LaTeX/MCP history breaking the prompt f-string template (
{2}→ValueError), freezing every follow-up turn on "Generating response…" — is fixed (escape_braceson the base system prompt). - Formulas render whatever notation the model picks:
$…$,$$…$$,```latex/```mathfences,\[…\],\(…\); dollar amounts stay literal (MathJax delimiter rules; code blocks skipped). The response prompt no longer teaches the model to wrap formulas in backticks.
Robustness riders
- State schema migrations wired (F7): the migration chain (zero callers since schema 1.0) now runs on every checkpoint load; new 1.2→1.3 step formalizes the ADR-092 replay-safe HITL keys +
user_display_name. - State persistence by contract (F5): response-node writes go through the state update (reducer-equivalent) instead of shared-reference mutation.
- Pure-ASGI middleware (F28): the 4 custom middlewares no longer spawn a per-request task-group + re-wrap every SSE chunk (PrometheusMiddleware untouched).
- Language-agnostic HITL token guard (FF2): structural
hitl_id prefix instead of hardcoded French sentences.
Docs & quality
ADR-093 (+ index entries), SECURITY.md, RATE_LIMITING.md, ARCHITECTURE.md (pure-ASGI), STATE_AND_CHECKPOINT.md (v1.3 chain wired); in-app FAQ changelog, HOW guides and the security blog article updated in all 6 languages. Ruff / Black / MyPy strict clean; backend 8518 tests green (+17), frontend 118 green (+18); every commit passed the full pre-commit hook.
Post-deploy validation (prod): app reachable via the tunnel; curl 192.168.0.14:8000 from the LAN refused; real public IPs in logs and Grafana.
Full changelog: https://github.com/jgouviergmail/LIA-Assistant/blob/main/CHANGELOG.md
Security Fixes
- Trusted proxy chain hardened: ports 8000/9091 loopback‑bound, uvicorn runs with --proxy-headers and safe forwarded‑allow‑ips.
- Chat markdown pipeline now uses rehype-sanitize to block script/iframes and other XSS vectors.
Weekly OSS security release digest.
The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.
No spam, unsubscribe anytime.
Share this release
About LIA
All releases →Related context
Related tools
Beta — feedback welcome: [email protected]