Chainlit 2.12.0: a `..;` segment bypasses the MCP allowed_urls path scope (CVE-2026-120492, no fix); 2.12.0 was the fix for SSRF CVE-2026-45019
TL;DR
Chainlit 2.12.0's validate_mcp_url does not reject the semicolon character, so an unauthenticated client can submit an MCP URL with ..; segments to /mcp and reach paths outside an operator's path-scoped allowed_urls grant on origins that strip semicolon path parameters (CVE-2026-120492, VulnCheck CNA, CVSS 4.0 6.3, published 2026-11-02; no fixed version, and 2.12.0 is the newest release on PyPI). The allowlist it bypasses is the one 2.12.0 introduced on 2026-08-25 to close CVE-2026-45019, an unauthenticated blind SSRF with attacker-chosen headers on the same endpoint that this corpus had not recorded. Chainlit deployments are exposed only with MCP enabled, user-supplied servers enabled and a path-prefixed allowlist entry; set features.mcp.user_servers.enabled = false, or features.mcp.enabled = false, until a release addresses it.
What happened
Chainlit is a Python framework for conversational AI front ends and a common chat UI in generated apps. Its POST /mcp endpoint lets a browser session connect the server to an MCP server by URL. Two advisories on 2026-08-25 (GitHub CNA, reporter qvipin of SPL, finder ladderlogix) covered that endpoint for 2.4.0rc0 through 2.11.1 when features.mcp.enabled = true in .chainlit/config.toml. CVE-2026-45018 (GHSA-w3fx-mc44-mf6j, 9.8) is command injection through the stdio transport's fullCommand, which the August batch file records. CVE-2026-45019 (GHSA-hvfh-5mj3-5f3j, 7.2 S:C/C:L/I:L) is an unauthenticated SSRF: the sse and streamable-http transports made outbound requests to any url with attacker-chosen headers, including Authorization and Cookie, so internal services and cloud metadata endpoints received authenticated-looking write requests. The SSRF is blind. Per the vendor advisory, MCP has been disabled by default since 2.7.0, which is why both are gated on the operator turning it on.
The 2.12.0 fix. Per the vendor advisory, 2.12.0 (PyPI 2026-08-25 17:01 UTC) replaced the open endpoint with an opt-in allowlist. User-provided MCP connections require features.mcp.user_servers.enabled = true and a non-empty allowed_urls list, and the default denies all. URLs must match an entry on scheme, host, port and path prefix, and "dangerous path encodings and non-ASCII paths are rejected". Restricted headers such as Cookie, Host, Forwarded and X-Forwarded-* are stripped while Authorization is still forwarded by design, redirects are no longer followed, and every outgoing request is rechecked against the grant. The advisory's own residual-risk section says there is no private-IP or IP-literal blocking and that header filtering is a denylist. The advisory's sidebar lists the patched version as "None" while its body names 2.12.0; the CNA records for both ids say >= 2.4.0rc0, < 2.12.0.
The bypass (CVE-2026-120492). VulnCheck's record, credited to Gavin Blacklock and published 2026-11-02 14:29 UTC, says 2.12.0 "allows unauthenticated attackers to bypass path-scoped MCP allowed_urls entries because validate_mcp_url does not reject the semicolon character. Attackers can submit MCP URLs with '..;' segments to the /mcp endpoint, causing requests to paths outside the operator's grant on origins that strip semicolon path parameters." The path-prefix check sees a path that stays inside the grant; a backend that treats ; as a path-parameter delimiter and strips it resolves the request elsewhere on the same origin. The record scores it 6.3 (CVSS 4.0, AT:P, SC:L/SI:L) and 5.4 (CVSS 3.1, AC:H), lists only version 2.12.0 as affected, names no fixed version, and references the August vendor advisory and two line ranges in backend/chainlit/mcp.py at the 2.12.0 tag. No vendor advisory, release or statement for this id was found on 2026-11-02; pip index versions chainlit lists 2.12.0 (2026-08-25) as newest.
Scope. The bypass needs an operator who enabled MCP, enabled user-supplied servers and wrote an allowlist entry with a path prefix on an origin that strips semicolon parameters. Host-only entries are not widened by it. What it reaches is other paths on an allowlisted origin, with the request still carrying whatever Authorization header the client sent. severity: medium follows the CNA's 6.3; status: mitigated because disabling user-supplied servers removes the path and no fix exists.
Am I affected?
pip show chainlit 2>/dev/null | grep -i ^version
grep -n 'mcp' .chainlit/config.toml 2>/dev/null # enabled, user_servers.enabled and allowed_urls
- Below 2.12.0 with
features.mcp.enabled = true: affected by CVE-2026-45018 and CVE-2026-45019, unauthenticated unless the deployment configures authentication. - 2.12.0 with
features.mcp.enabled = true,features.mcp.user_servers.enabled = trueand anallowed_urlsentry whose value includes a path: affected by CVE-2026-120492 on any such origin that strips semicolon path parameters. - MCP disabled: not affected by any of the three. On 2.12.0 with user servers disabled: not affected by CVE-2026-120492.
If you are affected
- Upgrade to 2.12.0 if below it; the 2.12.0 configuration change is breaking (legacy
[features.mcp.sse],[features.mcp.stdio]and[features.mcp.streamable-http]sections stop startup once MCP is enabled), so migrate to[[features.mcp.servers]]andallowed_urlsfirst; the vendor advisory points to the migration guide in the project'sCHANGELOG.md. - On 2.12.0, set
features.mcp.user_servers.enabled = falseuntil a release addresses CVE-2026-120492, or restrictallowed_urlsto origins you control and know do not strip semicolon path parameters. - If
/mcpwas reachable without authentication before 2.12.0, review what internal services and metadata endpoints the Chainlit host could reach and rotate any credential a blind write request could have used: if your web app was compromised, rotating cloud credentials.
Prevention
- Egress-filter the host that runs a chat framework; a server-side URL fetch is an SSRF primitive whatever allowlist sits in front of it: MCP hygiene, agent sandboxing.
- Require an authenticated session before any endpoint that makes the server connect somewhere.
Sources
- VulnCheck — Chainlit 2.12.0 SSRF via Semicolon Path Segment in MCP allowed_urls — fetched 2026-11-02: CVE-2026-120492, published 2026-11-02, Medium 6.3, the CVSS 4.0 vector, CWE-918, credit Gavin Blacklock, affected 2.12.0, no fixed version, references to GHSA-hvfh-5mj3-5f3j and
mcp.pyat the 2.12.0 tag. - CVE Services — CVE-2026-120492 — fetched 2026-11-02: CNA VulnCheck, published 2026-11-02 14:29 UTC, affected Chainlit 2.12.0, 6.3 (4.0) and 5.4 (3.1), the description quoted above.
- GitHub Advisory Database — GHSA-xhx7-9vjr-p2h8 — fetched 2026-11-02: CVE-2026-120492, Moderate, unreviewed, "No package listed", published 2026-11-02; the top row of the
mcprecency listing that day. - Chainlit — GHSA-hvfh-5mj3-5f3j: SSRF via MCP SSE and streamable-http transports allows unauthenticated internal network access — fetched 2026-11-02: CVE-2026-45019, published 2026-08-25 by willydouhard, 7.2, affected
>= 2.4.0rc0, <= 2.11.1in the sidebar and< 2.12.0in the body, patched "None" in the sidebar and 2.12.0 in the body, credits, the fix design, workarounds and residual-risk sections summarised above. - GitHub Advisory Database — GHSA-w3fx-mc44-mf6j — fetched 2026-11-02: CVE-2026-45018, 9.8, stdio
fullCommandinjection, patched 2.12.0, names CVE-2026-45019 as the companion. - CVE Services — CVE-2026-45019 and CVE-2026-45018 — fetched 2026-11-02: CNA GitHub_M, published 2026-08-25, affected
>= 2.4.0rc0, < 2.12.0, 7.2 and 9.8. - PyPI
chainlitrelease metadata, queried 2026-11-02: 2.11.1 2026-04-22, 2.12.0 2026-08-25 17:01 UTC, newest 2.12.0. - Related in this corpus: August 2026 agent-framework and MCP-server CVE batch (CVE-2026-45018).