CVE-2026-45019: Chainlit: unauth SSRF via MCP url/header injection
GHSA-hvfh-5mj3-5f3jHIGHPoC AVAILABLEChainlit's MCP integration accepts an unauthenticated, user-supplied URL and HTTP headers and forwards them straight into outbound server-side requests, turning the `/mcp` endpoint into a blind SSRF primitive that can forge `Authorization` and `Cookie` headers against internal services or cloud metadata endpoints. The flaw has existed since MCP support first shipped in v2.4.0rc0, with attacker-controlled header forwarding added in v2.6.4, so any deployment between those versions and 2.12.0 running with `features.mcp.enabled = true` is exposed to any client able to open a session — no credentials needed. There's no public exploit or scanner template yet and it isn't in CISA KEV, but the PoC is three curl commands: no AI/ML expertise is required, and the blast radius extends to all 41 packages that depend on chainlit. MCP has been off by default since v2.7.0, so most deployments are unaffected out of the box, but any team that explicitly enabled it for tool integrations is exposed until patched. Upgrade to Chainlit 2.12.0 (note the breaking MCP config migration), or in the interim set `features.mcp.enabled = false`, require authentication on the app, and restrict outbound egress from the Chainlit host to internal ranges and the cloud metadata address.
What is the risk?
CVSS 7.2 (High), AV:N/AC:L/PR:N/UI:N — network-reachable, low complexity, no privileges or user interaction required. Exploitability is trivial: the PoC is unauthenticated HTTP requests with no AI/ML-specific knowledge needed. Impact is capped at confidentiality/integrity-low per CVSS because the SSRF is blind (no response returned to the attacker), but the writeup correctly notes that with full control of both destination URL and headers, an attacker can still issue state-changing, authenticated POST/PUT requests to internal APIs without needing to read the response — this is a stronger primitive than typical blind SSRF. Real-world exposure is mitigated by MCP being opt-in and off by default since v2.7.0; risk concentrates in the subset of deployments that deliberately enabled MCP tool integrations, which is exactly the population most likely to expose Chainlit as an internet-facing agent/chat front-end. No public exploit code, no Nuclei template, not in CISA KEV, and EPSS data is unavailable — treat as high-priority patch-on-next-cycle rather than emergency, unless MCP is enabled and internet-facing.
How does the attack unfold?
What systems are affected?
| Package | Ecosystem | Vulnerable Range | Patched |
|---|---|---|---|
| Chainlit | pip | >= 2.4.0rc0, <= 2.11.1 | 2.12.0 |
Do you use Chainlit? You're affected.
How severe is it?
What is the attack surface?
What should I do?
1 stepPatch to Chainlit 2.12.0, which enforces deny-by-default: user-provided MCP connections require explicit opt-in (
features.mcp.user_servers.enabled = true) plus a non-emptyallowed_urlsallowlist, strips dangerous headers (Cookie, Host, X-Forwarded-*, etc.), and stops following redirects on MCP transports. Note the breaking config change — legacy[features.mcp.sse]/[stdio]/[streamable-http]sections must be migrated to[[features.mcp.servers]]before MCP can be re-enabled. If immediate upgrade isn't possible: setfeatures.mcp.enabled = false(fully closes this issue and the companion stdio command-injection CVE-2026-45018), restrict outbound egress from the Chainlit host to internal ranges and the metadata endpoint, and/or configure an auth callback so/mcprequires an authenticated session. Post-upgrade, remember the residual risk:/mcpstays reachable anonymously if no auth callback is registered, and the allowlist is hostname-based with no private-IP/IP-literal blocking, so DNS rebinding to loopback/link-local/metadata addresses is still possible. Detection: monitor Chainlit host egress logs for connections to RFC1918 ranges or 169.254.169.254, and alert on unexpectedAuthorization/Cookieheader values on outbound requests originating from the app server.
What does CISA's SSVC say?
Source: CISA Vulnrichment (SSVC v2.0). Decision based on the CISA Coordinator decision tree.
How is it classified?
Which compliance frameworks are affected?
This CVE is relevant to:
Frequently Asked Questions
What is CVE-2026-45019?
Chainlit's MCP integration accepts an unauthenticated, user-supplied URL and HTTP headers and forwards them straight into outbound server-side requests, turning the `/mcp` endpoint into a blind SSRF primitive that can forge `Authorization` and `Cookie` headers against internal services or cloud metadata endpoints. The flaw has existed since MCP support first shipped in v2.4.0rc0, with attacker-controlled header forwarding added in v2.6.4, so any deployment between those versions and 2.12.0 running with `features.mcp.enabled = true` is exposed to any client able to open a session — no credentials needed. There's no public exploit or scanner template yet and it isn't in CISA KEV, but the PoC is three curl commands: no AI/ML expertise is required, and the blast radius extends to all 41 packages that depend on chainlit. MCP has been off by default since v2.7.0, so most deployments are unaffected out of the box, but any team that explicitly enabled it for tool integrations is exposed until patched. Upgrade to Chainlit 2.12.0 (note the breaking MCP config migration), or in the interim set `features.mcp.enabled = false`, require authentication on the app, and restrict outbound egress from the Chainlit host to internal ranges and the cloud metadata address.
Is CVE-2026-45019 actively exploited?
Proof-of-concept exploit code is publicly available for CVE-2026-45019, increasing the risk of exploitation.
How to fix CVE-2026-45019?
Patch to Chainlit 2.12.0, which enforces deny-by-default: user-provided MCP connections require explicit opt-in (`features.mcp.user_servers.enabled = true`) plus a non-empty `allowed_urls` allowlist, strips dangerous headers (Cookie, Host, X-Forwarded-*, etc.), and stops following redirects on MCP transports. Note the breaking config change — legacy `[features.mcp.sse]`/`[stdio]`/`[streamable-http]` sections must be migrated to `[[features.mcp.servers]]` before MCP can be re-enabled. If immediate upgrade isn't possible: set `features.mcp.enabled = false` (fully closes this issue and the companion stdio command-injection CVE-2026-45018), restrict outbound egress from the Chainlit host to internal ranges and the metadata endpoint, and/or configure an auth callback so `/mcp` requires an authenticated session. Post-upgrade, remember the residual risk: `/mcp` stays reachable anonymously if no auth callback is registered, and the allowlist is hostname-based with no private-IP/IP-literal blocking, so DNS rebinding to loopback/link-local/metadata addresses is still possible. Detection: monitor Chainlit host egress logs for connections to RFC1918 ranges or 169.254.169.254, and alert on unexpected `Authorization`/`Cookie` header values on outbound requests originating from the app server.
What systems are affected by CVE-2026-45019?
This vulnerability affects the following AI/ML architecture patterns: agent frameworks, chat/inference UI front-ends, RAG pipelines.
What is the CVSS score for CVE-2026-45019?
CVE-2026-45019 has a CVSS v3.1 base score of 7.2 (HIGH). The EPSS exploitation probability is 0.43%.
What is the AI security impact?
Affected AI Architectures
MITRE ATLAS Techniques
AML.T0006Active ScanningAML.T0049Exploit Public-Facing ApplicationAML.T0075Cloud Service DiscoveryCompliance Controls Affected
What are the technical details?
Original Advisory
Chainlit is a Python framework for building production-ready conversational AI applications. From 2.4.0rc0 until 2.12.0, Chainlit deployments with features.mcp.enabled set to true in .chainlit/config.toml expose the POST /mcp endpoint without requiring authentication. For sse and streamable-http transports, ConnectSseMCPRequest and ConnectStreamableHttpMCPRequest in backend/chainlit/types.py accept a user-controlled url and optional headers dictionary without scheme validation, private-address filtering, or an allowlist. The connect_mcp handler in backend/chainlit/server.py passes these values to sse_client() or streamablehttp_client(), allowing the Chainlit server to make blind outbound requests to arbitrary internal or external services, including cloud metadata endpoints, with attacker-controlled Authorization and Cookie headers. The SSE URL sink has existed since 2.4.0rc0, while attacker-controlled header forwarding and streamable-http support were added in 2.6.4. The response is consumed internally and not returned, but the attacker can issue state-changing authenticated requests, discover internal services, scan ports, and probe metadata endpoints. This issue is fixed in version 2.12.0.
Exploitation Scenario
An attacker finds an internet-facing Chainlit deployment with MCP tool integration enabled (e.g., discovered via Shodan/fingerprinting or simply because it's the company's public AI assistant). Without any credentials, they open a Socket.IO session, then POST to `/mcp` with `clientType: streamable-http` and a `url` pointing at an internal admin API (or the cloud metadata endpoint), attaching a forged `Authorization: Bearer` header and internal-only headers they've guessed or harvested from prior recon. The Chainlit server issues the outbound request on the attacker's behalf; even though the response is never returned, a POST/PUT to an internal write endpoint still executes. The attacker repeats this against different internal hosts and ports to map the internal network, and separately targets 169.254.169.254 to attempt IAM credential theft from the cloud metadata service — all without ever needing to see a response.
Weaknesses (CWE)
CWE-918Server-Side Request Forgery (SSRF)PrimaryCWE-918Server-Side Request Forgery (SSRF)PrimaryCWE-918Server-Side Request Forgery (SSRF)CWE-918 — Server-Side Request Forgery (SSRF): The web server receives a URL or similar request from an upstream component and retrieves the contents of this URL, but it does not sufficiently ensure that the request is being sent to the expected destination.
Source: MITRE CWE corpus.
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:NReferences
- github.com/Chainlit/chainlit/blob/2.12.0/docs/security-advisory-2026-mcp.md
- github.com/Chainlit/chainlit/commit/0565fd0eccb915fce159929598b053ed79f6e0c9
- github.com/Chainlit/chainlit/releases/tag/2.12.0
- github.com/Chainlit/chainlit/security/advisories/GHSA-hvfh-5mj3-5f3j
- github.com/advisories/GHSA-hvfh-5mj3-5f3j
Timeline
Related Vulnerabilities
CVE-2026-450189.8Chainlit: unauth RCE via MCP stdio cmd injection
Same package: chainlitCVE-2026-561048.2Chainlit: session hijacking via WebSocket restoration
Same package: chainlitCVE-2026-860998.2Chainlit: path traversal via sessionId wipes directories
Same package: chainlitCVE-2026-222197.7chainlit: SSRF allows internal network access
Same package: chainlitCVE-2026-822905.3Chainlit: IDOR lets users tamper with others' feedback
Same package: chainlit