Part of VforVitorio#884 (Fable-5 red-team audit 2026-07-05). Sprint 1 — MCP exec & CSRF boundary (P0). The headline: unauthenticated MCP-server registration whose command is later spawned, reachable as CSRF→RCE from the browser (and direct unauth RCE if ever networked). Full trace in memory/fable_redteam_audit_2026-07-05.md (issue text kept non-exploitable).
⚠️ Unpatched RCE on a public repo — consider a private GitHub Security Advisory for this sprint.
Full detail: memory/fable_redteam_audit_2026-07-05.md.
Upstream: VforVitorio#885
Part of VforVitorio#884 (Fable-5 red-team audit 2026-07-05). Sprint 1 — MCP exec & CSRF boundary (P0). The headline: unauthenticated MCP-server registration whose command is later spawned, reachable as CSRF→RCE from the browser (and direct unauth RCE if ever networked). Full trace in
memory/fable_redteam_audit_2026-07-05.md(issue text kept non-exploitable).security(mcp): consent-before-spawn for external MCP servers (no auto-connect)[M] [P0] — an added/imported server'scommandstring is spawned as a stdio subprocess on the firstGET /api/v1/mcp/tools(chat/mcp_client.py:26-28,102-124,182-211);command/argshave NO allow-list (api/routers/mcp_servers.py:107;mcp_servers/schemas.py:69-98validates onlyurl); the.mcpbbundle path isapi/routers/mcp_servers.py:248+mcp_servers/bundle.py:226-251. AC: require explicit in-SPA user consent before the FIRST spawn of any newly added/imported server; never auto-connect on add/import. (P0-1, RCE)security(api): Origin/Host allow-list on state-changing + spawn-triggering routes[M] [P0] — onlyRequestIdMiddlewareis installed; no auth/CSRF gate anywhere (api/app.py:129). The browser-reachable subset — bodylessPOST /sync,POST /system/semantic-install,GET /mcp/tools, multipartPOST /mcp/bundles(multipart = CORS "simple request", no preflight) — is CSRF-able. AC: reject cross-origin state-changing requests via an Origin/Host allow-list (or a required custom header the SPA sets). (P0/P1-2)security(deploy): assert + document the 127.0.0.1 bind as a hard security boundary[S] —main.py:9. AC: startup assertion / explicit opt-in + loud warning when bound off-loopback; require real auth before any networked/multi-user mode; note in packaging ([epic] Legal chat — trust & UX (Fable 5 audit) #37) + CONTRIBUTING. (P0/P1-2)security(mcp): sandbox spawned MCP servers (stretch, defense-in-depth)[S] — the_build_configseam atchat/mcp_client.py:127is already flagged for this. (P0-1)Full detail:
memory/fable_redteam_audit_2026-07-05.md.Upstream: VforVitorio#885