Threat · curated 7 Sep 2026
The Notebook Backdoor: jupyter-mcp-server Vulnerabilities
First reported pluto.security
Coverage timeline
Single-source advisory — first reported, latest, and curated coincide.
Why it matters
jupyter-mcp-server bridges AI agents into live Jupyter notebooks holding internal company data, so these MCP flaws let a single browser tab hijack an agent's connection and exfiltrate or poison that data without any network access.
Pluto Security disclosed two vulnerabilities in Datalayer's jupyter-mcp-server (400K+ downloads): CVE-2026-77318 (CVSS 7.3) exposes /api/connect and /api/stop with no authentication, and CVE-2026-77359 (CVSS 9.3) leaves those routes missing Host/Origin checks, enabling DNS rebinding. Chaining them lets any malicious website a victim visits silently redirect an AI assistant's live notebook backend to read or plant data with zero clicks, and even Claude on Opus 4.8 failed to notice the swap. A fix is available in v1.0.3.
Summary
Pluto Security researchers disclosed two chained vulnerabilities in Datalayer's jupyter-mcp-server, the official MCP bridge for Jupyter with over 400K downloads. CVE-2026-77318 (CVSS 7.3) leaves the /api/connect and /api/stop routes completely unauthenticated, and CVE-2026-77359 (CVSS 9.3) leaves those same routes exempt from the Host/Origin validation that protects the /mcp endpoint, opening a DNS-rebinding path.[1][4][5]
Individually, the missing-auth bug requires an attacker to reach the machine running the server, but chained with DNS rebinding it becomes a zero-click web attack: any malicious website a victim visits can silently repoint the assistant's live notebook connection to attacker-controlled infrastructure, enabling exfiltration of confidential notebook data or permanent pollution of the victim's notebooks without either the user or the LLM noticing.[1]
The findings were reported on July 6 and fixed in v1.0.3, released July 11, with the maintainer's fix adding a single middleware that applies the same authentication and Host/Origin checks to the custom routes. There is no evidence of in-the-wild exploitation; the demonstrations were researcher proof-of-concept scenarios.[1][3]
Attack chain
- Delivery (DNS rebinding): A victim running jupyter-mcp-server visits a malicious website. The page's hostname initially resolves to the attacker's server, then flips to 127.0.0.1 mid-session; the browser still treats it as the same origin and keeps sending requests, which now land on the local server. Because custom_route handlers bypass the MCP SDK transport's Host/Origin validation, the forged request is accepted (CVE-2026-77359).[1]
- Exploitation (unauthenticated backend switch): The forged request hits PUT /api/connect (or DELETE /api/stop), which perform no authentication check (CVE-2026-77318). The attacker supplies an attacker-chosen runtime_url and document_url; the server resets its context and connects to the attacker-controlled Jupyter backend.[1]
- Impact — exfiltration: After the assistant reads confidential notebook data into its context, the attacker swaps the backend to a decoy notebook on attacker infrastructure. When the user asks the assistant to save a summary, the data is written to the attacker's server while the tool call still reports success. No 'backend changed' event reaches the model.[1]
- Impact — data pollution: The attacker repoints the connection to a lookalike decoy notebook with one figure quietly changed, lets the assistant read the false value as fact, then repoints back to the victim's real file so the assistant writes the false figure permanently into the genuine notebook.[1]
Disclosure timeline
| Date | Event |
|---|---|
| July 6 | Both findings reported to Datalayer: missing auth on /api/connect and /api/stop, and the DNS-rebinding path via the same routes' missing Host/Origin checks.[1] |
| July 8 | Fix PR #262 opened, covering both issues in a single middleware.[1][3] |
| July 11 | PR #262 merged (commit c2e98fc) and released in v1.0.3; advisory GHSA-24pw-rf5p-mgp7 published (CVSS 7.3, High).[1][4] |
| July 12 | Advisory GHSA-9x8x-crjq-g64h published (CVSS 9.3, Critical).[1][5] |
How it works
jupyter-mcp-server exposes /api/connect and /api/stop alongside the main /mcp endpoint so an assistant can switch which notebook or server it drives. The connect handler reads runtime_url and document_url from the request body and adopts them, resetting ServerContext and restarting the kernel, but never checks who the caller is. Authentication (a bearer token) had been added to /mcp in PR #232, but the later-added /api/connect and /api/stop were never wired into that check, so anyone able to reach the port can silently redirect the notebook backend (CVE-2026-77318).[1][2]
The Python MCP SDK enforces Host/Origin validation on /mcp by default as built-in DNS-rebinding protection, but that check only applies to routes dispatched through the SDK's transport handler. Routes registered with @mcp.custom_route() bypass it entirely. A forged request with an invalid Host/Origin header returns 421 on /mcp but 200 OK on /api/connect, so DNS rebinding delivers an attacker-controlled request straight to the unauthenticated route (CVE-2026-77359).[1]
The abuse is invisible to the model: because the assistant talks to Jupyter over real-time collaboration and continues using a connection the user already trusted, MCP sends no 'backend changed' event. No prompt injection or suspicious instruction reaches the model, so higher reasoning effort provides no protection — Claude on Opus 4.8 with high reasoning never detected the swap.[1]
Affected versions and patch status
| Product | Affected | Patch status |
|---|---|---|
| datalayer jupyter-mcp-server (standalone HTTP mode) | Versions prior to v1.0.3; vulnerable code demonstrated at commit 27b91e5 | Fixed in v1.0.3 (PR #262, merged as commit c2e98fc); upgrade to v1.0.3 or later[1][3] |
Key takeaways
- The vulnerability was not a prompt injection or jailbreak — the model behaved exactly as designed. The broken part was the system boundary: the backend connection could change with no signal to the user or the assistant.[1]
- Adding custom HTTP routes outside a framework's transport handler can silently bypass built-in protections (here, authentication and DNS-rebinding Host/Origin validation), so security checks must be applied uniformly at a middleware layer.[1]
- DNS rebinding can erase an attacker's network-position requirement, converting a local/same-network flaw into a zero-click web attack reachable by simply luring a victim to a malicious page.[1]
Defensive actions
- Upgrade jupyter-mcp-server to v1.0.3 or later, especially if running in standalone HTTP mode.: v1.0.3 adds a middleware that applies the Host/Origin and bearer-token checks to /api/connect and /api/stop, closing both CVE-2026-77318 and CVE-2026-77359.[1][3]
- Inventory and audit MCP servers and other AI connectors running across the organization, including self-hosted ones.: Pluto notes that widely adopted MCP servers are running unaudited with exactly these trust-boundary gaps; data analysts, data scientists, and ML engineers who run these servers hold sensitive internal data on their machines.[1]