Skip to content

Chainlit MCP

Summary

Chainlit published two GitHub Security Advisories on August 25, 2026 covering unauthenticated flaws in its MCP (Model Context Protocol) endpoint, both fixed in Chainlit 2.12.0 (released to PyPI 2026-08-25):

  • CVE-2026-45018 (GHSA-w3fx-mc44-mf6j, CVSS 9.8 Critical, CWE-78): command injection / remote code execution via the MCP stdio transport. The POST /mcp endpoint accepts a user-controlled fullCommand string; validate_mcp_command() checks only the executable name against config.features.mcp.stdio.allowed_executables and does not inspect arguments. npx -y -c 'PAYLOAD' passes the allowlist check while executing arbitrary shell commands with the privileges of the Chainlit process.
  • CVE-2026-45019 (GHSA-hvfh-5mj3-5f3j, CVSS 7.2 High, CWE-918): SSRF via the MCP sse and streamable-http transports. The request model defines url as a bare str with no scheme check, no private-IP filtering, and no allowlist, and (since 2.6.4) forwards attacker-controlled headers (e.g. Authorization, Cookie) to the target, enabling requests to internal services and cloud metadata endpoints.

Both require the operator to have set features.mcp.enabled = true in .chainlit/config.toml. MCP has been disabled by default since v2.7.0, so most deployments are not exposed. No authentication is required: /mcp is reachable by any client that can open a session. No exploitation, actor, or infrastructure detail is named in the advisories.

Tags

Vulnerability mechanics

  • Gate: both flaws live in the optional MCP feature. Impact requires features.mcp.enabled = true; the default since v2.7.0 is disabled.
  • CVE-2026-45018 (stdio): validate_mcp_command() in backend/chainlit/mcp.py parses the command with shlex.split() and allowlists only the executable name. Arguments are returned unchecked and passed to StdioServerParameters, which spawns the subprocess. Because npx supports -c for arbitrary shell execution, a command whose name is allowlisted (npx, uvx, …) still runs attacker-chosen commands: npx -y -c 'PAYLOAD'. Introduced when MCP support landed (PR #1977), affecting >=2.4.0rc0, <2.12.0.
  • CVE-2026-45019 (sse / streamable-http): the Pydantic request models in backend/chainlit/types.py accept url as an unvalidated string; the handler in backend/chainlit/server.py passes the URL and optional headers dictionary directly to the MCP SDK's sse_client() / streamablehttp_client(), which issue server-side outbound HTTP requests. The URL sink has existed since MCP support was introduced (PR #1977, >=2.4.0rc0); attacker-controlled header forwarding that amplifies it (credential/metadata exfil via spoofed Authorization/Cookie) was added in PR #2292 (>=2.6.4).
  • Fix: 2.12.0 (commit 0565fd0eccb915fce159929598b053ed79f6e0c9, release 2026-08-25); see also Chainlit's security advisory doc (docs/security-advisory-2026-mcp.md, SPL-2026-002 for the SSRF).

Defender heuristics

  1. Check the config, not just the version: on every exposed or internal Chainlit host, verify whether features.mcp.enabled is set. If MCP is not enabled, these flaws are not reachable; if it is enabled, treat the host as compromised-adjacent until 2.12.0.
  2. Upgrade to 2.12.0 on any deployment with MCP enabled; 2.12.0 shipped to PyPI on 2026-08-25 (advisory published the same evening, 2026-08-25 ~19:19/19:21 UTC).
  3. Hunt for post-exploitation artifacts on hosts that ran >=2.4.0rc0 with MCP enabled: unexpected npx -c / uvx child processes of the Chainlit service, new accounts/services, outbound requests from the Chainlit process to internal or 169.254.169.254/metadata endpoints with anomalous headers.
  4. Network-control the surface: restrict who can open a session to /mcp; egress-filter server-side outbound requests from the Chainlit process where possible. The RCE path is a textbook MCP stdio command-execution boundary failure, the same pattern as marimo's notebook-metadata MCP command injection (see related pages).
  5. Inventory AI-tooling MCP servers generally: this is part of a recurring class of MCP trust-boundary flaws (Meta Ads MCP unauthenticated tool execution, Grafana MCP readable-SSRF, Flyto2 Core callback secret disclosure) where MCP transports turn a reachable app into an unauthenticated proxy/executor.

Sources