Jupyter Server's Origin header validation uses re.match() instead of re.fullmatch(), allowing any attacker who controls a domain starting with the trusted pattern (e.g., trusted.example.com.evil.com) to bypass CORS protections entirely. With 1,862 downstream dependents and Jupyter's near-universal presence in AI/ML development environments, this creates a wide cross-origin attack surface where a malicious web page can reach the Jupyter kernel API and execute arbitrary code against any unpatched instance — the EPSS places this in the top 87th percentile for exploitation likelihood despite low absolute probability. Patch to jupyter-server 2.18.0 immediately; if patching is not possible, anchor all allow_origin_pat values with ^ and $ as an interim workaround.
What is the risk?
HIGH risk for organizations where Jupyter Server is deployed on internal networks or developer workstations accessible from a browser. The vulnerability is straightforward to weaponize — an attacker needs only to register a domain that begins with the trusted prefix and serve a malicious page. Jupyter's kernel API permits arbitrary Python execution, so a successful CORS bypass grants effectively full code execution on the server with the process owner's privileges, making this a high-impact stepping stone into AI/ML development pipelines.
How does the attack unfold?
What systems are affected?
| Package | Ecosystem | Vulnerable Range | Patched |
|---|---|---|---|
| Jupyter | pip | <= 2.17.0 | 2.18.0 |
Do you use Jupyter? You're affected.
How severe is it?
What should I do?
5 steps-
Patch: Upgrade jupyter-server to 2.18.0 (commits 057869a and 49b3439 resolve the issue).
-
Workaround: Immediately audit all allow_origin_pat configuration values and wrap each pattern with ^ and $ anchors (e.g., change trusted\.example\.com to ^trusted\.example\.com$).
-
Network controls: Restrict Jupyter Server access to localhost or trusted internal subnets; never expose Jupyter directly to the internet.
-
Audit dependents: Check whether downstream packages (JupyterLab, JupyterHub, notebook) in your environment pull jupyter-server <= 2.17.0 and upgrade those dependency chains.
-
Detection: Monitor web proxy and WAF logs for cross-origin requests to Jupyter endpoints (/api/kernels, /api/sessions) from unexpected origins.
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-40110?
Jupyter Server's Origin header validation uses re.match() instead of re.fullmatch(), allowing any attacker who controls a domain starting with the trusted pattern (e.g., trusted.example.com.evil.com) to bypass CORS protections entirely. With 1,862 downstream dependents and Jupyter's near-universal presence in AI/ML development environments, this creates a wide cross-origin attack surface where a malicious web page can reach the Jupyter kernel API and execute arbitrary code against any unpatched instance — the EPSS places this in the top 87th percentile for exploitation likelihood despite low absolute probability. Patch to jupyter-server 2.18.0 immediately; if patching is not possible, anchor all allow_origin_pat values with ^ and $ as an interim workaround.
Is CVE-2026-40110 actively exploited?
No confirmed active exploitation of CVE-2026-40110 has been reported, but organizations should still patch proactively.
How to fix CVE-2026-40110?
1. Patch: Upgrade jupyter-server to 2.18.0 (commits 057869a and 49b3439 resolve the issue). 2. Workaround: Immediately audit all allow_origin_pat configuration values and wrap each pattern with ^ and $ anchors (e.g., change trusted\.example\.com to ^trusted\.example\.com$). 3. Network controls: Restrict Jupyter Server access to localhost or trusted internal subnets; never expose Jupyter directly to the internet. 4. Audit dependents: Check whether downstream packages (JupyterLab, JupyterHub, notebook) in your environment pull jupyter-server <= 2.17.0 and upgrade those dependency chains. 5. Detection: Monitor web proxy and WAF logs for cross-origin requests to Jupyter endpoints (/api/kernels, /api/sessions) from unexpected origins.
What systems are affected by CVE-2026-40110?
This vulnerability affects the following AI/ML architecture patterns: ML development environments, Training pipelines using notebook orchestration, JupyterHub multi-user deployments, MLOps pipelines with programmatic notebook execution, Data science workstations with browser-accessible Jupyter.
What is the CVSS score for CVE-2026-40110?
No CVSS score has been assigned yet.
What is the AI security impact?
Affected AI Architectures
MITRE ATLAS Techniques
AML.T0008.002 Domains AML.T0025 Exfiltration via Cyber Means AML.T0035 AI Artifact Collection AML.T0049 Exploit Public-Facing Application Compliance Controls Affected
What are the technical details?
Original Advisory
Jupyter Server uses `re.match()` to validate the Origin header against the `allow_origin_pat` configuration. Since `re.match()` only anchors at the start of the string, an attacker who controls a domain like `http://trusted.example.com.evil.com/` passes validation against a pattern intended to match only `trusted.example.com`. ### Impact <=2.17.0 ### Patches 057869a327c46730afede3eab0ca2d2e3e74acea, 49b34392feaa97735b3b777e3baf8f22f2a14ed8 ### Workarounds Wrap your `allow_origin_pat` value with `^` and `$` ### References https://github.com/jupyter-server/jupyter_server/pull/603 https://docs.python.org/3/library/re.html#re.fullmatch https://docs.python.org/3/library/re.html#re.match
Exploitation Scenario
An adversary targeting an AI development team registers trusted.example.com.evil.com — a domain crafted to match the victim's allow_origin_pat regex at the start while appending an attacker-controlled suffix. They deploy a malicious page on this domain with JavaScript that fetches the list of active Jupyter kernels (GET /api/kernels), selects one, and posts an execute request (POST /api/kernels/<id>/execute) containing Python code to read notebook files, harvest embedded cloud API keys or model registry tokens, and exfiltrate them to the attacker's infrastructure. A targeted phishing email lures a developer to visit the malicious page; since the browser sends the crafted Origin header and Jupyter's re.match() check passes, CORS headers are returned, the browser lifts the same-origin restriction, and the JavaScript silently exfiltrates the environment's AI artifacts without any user interaction beyond the initial page load.
Weaknesses (CWE)
CWE-777 — Regular Expression without Anchors: The product uses a regular expression to perform neutralization, but the regular expression is not anchored and may allow malicious or malformed data to slip through.
- [Implementation] Be sure to understand both what will be matched and what will not be matched by a regular expression. Anchoring the ends of the expression will allow the programmer to define an allowlist strictly limited to what is matched by the text in the regular expression. If you are using a package that only matches one line by default, ensure that you can match multi-line inputs if necessary.
Source: MITRE CWE corpus.
References
Timeline
Related Vulnerabilities
CVE-2023-25574 10.0 JupyterHub LTI13: JWT forgery enables full auth bypass
Same package: jupyter CVE-2026-44180 9.8 Jupyter Enterprise Gateway: root privilege bypass in Kubernetes
Same package: jupyter CVE-2026-42266 8.8 JupyterLab: Extension allow-list bypass enables privesc
Same package: jupyter CVE-2026-5422 8.1 jupyter-server: path traversal exposes sibling dir files
Same package: jupyter CVE-2025-30370 7.4 jupyterlab-git: command injection via malicious repo name
Same package: jupyter