CVE-2026-40171 - Jupyter CommandLinker token theft
Jupyter Notebook and JupyterLab shipped a stored XSS path in command-linker handling used by the help extensions. A malicious notebook or Markdown file can present a UI element that looks like a normal Jupyter control; when a signed-in user interacts with it, attacker-controlled script can obtain the user’s Jupyter authentication token.
The token is enough to act through the Jupyter REST API as that user. In a shared AI notebook environment, that can become file access, file modification, kernel access, arbitrary code execution through running kernels, or terminal creation. For agentic AI platforms, the risk is larger than a browser bug: a notebook is both context and execution surface, so untrusted notebook content must not be able to cross into session authority.
Affected versions
- Vulnerable:
notebook >=7.0.0, <=7.5.5 - Fixed:
notebook 7.5.6+ - Vulnerable:
jupyterlab <=4.5.6 - Fixed:
jupyterlab 4.5.7+ - Vulnerable npm package:
@jupyter-notebook/help-extension >=7.0.0, <=7.5.5 - Fixed npm package:
@jupyter-notebook/help-extension 7.5.6+ - Vulnerable npm package:
@jupyterlab/help-extension <=4.5.6 - Fixed npm package:
@jupyterlab/help-extension 4.5.7+
Indicator-of-exposure
- The repository builds, deploys, or configures Jupyter Notebook 7.x, JupyterLab, JupyterHub images, Codespaces/devcontainer notebook images, data-science workbenches, ML training sandboxes, or agent notebook workspaces.
- Any resolved
notebookpackage is>=7.0.0, <=7.5.5. - Any resolved
jupyterlabpackage is<=4.5.6. - Frontend bundles, labextension locks, or package manager metadata include
vulnerable
@jupyter-notebook/help-extensionor@jupyterlab/help-extensionversions. - Users, agents, reviewers, or CI jobs may open notebooks, Markdown files, or generated reports from untrusted repositories, uploads, tickets, chats, or model outputs.
- The Jupyter server can read project files, dataset mounts, model artifacts, cloud credentials, workspace secrets, Git credentials, SSH keys, or internal network resources.
Quick checks:
rg -n "jupyterlab|notebook|jupyterhub|@jupyterlab/help-extension|@jupyter-notebook/help-extension|allowCommandLinker|data-commandLinker" .
python -m pip show notebook jupyterlab
pip freeze | rg "^(notebook|jupyterlab)=="
npm ls @jupyterlab/help-extension @jupyter-notebook/help-extension
rg -n "jupyter labextension disable|overrides\\.json|apputils-extension:sanitizer|NotebookApp|ServerApp" Dockerfile* docker-compose*.yml pyproject.toml requirements*.txt environment*.yml package*.json pnpm-lock.yaml yarn.lock charts deploy k8s .devcontainer .Remediation strategy
- Upgrade every controlled Notebook deployment to
notebook 7.5.6+. - Upgrade every controlled JupyterLab deployment to
jupyterlab 4.5.7+. - Regenerate Python locks, environment files, frontend/labextension locks, container image digests, SBOMs, workspace templates, and deployment render output.
- Where users or agents may open untrusted notebooks, disable command-linker
behavior even after upgrade by setting sanitizer policy such as
allowCommandLinker: false. - Until patched images are deployed, disable the vulnerable help extensions in controlled runtime images or startup hooks.
- Treat this as a session-token exposure if untrusted notebooks were opened in a vulnerable shared workspace. Rotate relevant workspace tokens, invalidate sessions where possible, and review Jupyter access logs for unusual file, kernel, and terminal activity.
The prompt
Model context: this prompt was generated by GPT 5.5 Extra High reasoning.
You are remediating CVE-2026-40171 / GHSA-rch3-82jr-f9w9 (Jupyter
Notebook/JupyterLab stored XSS that can steal Jupyter auth tokens through
command-linker content). Produce exactly one output:
- A reviewer-ready PR/change request that upgrades Jupyter, disables or
constrains command-linker behavior for untrusted notebook contexts, adds
safe verification, and documents operator cleanup, or
- TRIAGE.md if this repository does not own an affected Jupyter runtime or
cannot make a safe patch.
## Rules
- Scope only CVE-2026-40171 / GHSA-rch3-82jr-f9w9 and directly related Jupyter
command-linker hardening.
- Treat Jupyter auth tokens, API tokens, kernels, terminal sessions, workspace
files, notebooks, datasets, model artifacts, cloud credentials, Git
credentials, SSH keys, and browser session data as sensitive.
- Do not create or open an exploit notebook against production, staging,
shared dev, hosted notebook, or user workspaces.
- Do not print, snapshot, commit, or attach real Jupyter tokens, cookies,
file contents, terminal output, kernel output, or secret-bearing notebook
cells.
- Do not preserve command-linker behavior for untrusted notebook ingestion
unless a product/security owner explicitly accepts the risk in the PR.
- Do not auto-merge.
## Steps
1. Inventory every Jupyter runtime controlled by this repository:
Python manifests, lockfiles, Conda environment files, Dockerfiles,
devcontainers, Codespaces config, JupyterHub images, Helm charts,
Kubernetes manifests, Terraform, Ansible, notebook workspace templates,
frontend extension bundles, SBOMs, runbooks, and CI images.
2. Determine every resolved version:
- `notebook` is vulnerable if it resolves to `>=7.0.0, <=7.5.5`;
- `jupyterlab` is vulnerable if it resolves to `<=4.5.6`;
- `@jupyter-notebook/help-extension` is vulnerable if it resolves to
`>=7.0.0, <=7.5.5`;
- `@jupyterlab/help-extension` is vulnerable if it resolves to `<=4.5.6`.
3. Determine exposure without exploit testing:
- Can users, agents, reviewers, CI jobs, or support staff open notebooks or
Markdown files from untrusted repositories, uploads, tickets, chats, or
model outputs?
- Does the runtime expose kernels, terminals, dataset mounts, model
artifacts, source code, cloud credentials, or internal network access?
- Are Jupyter tokens long-lived, shared, logged, embedded in URLs, or
reachable by browser JavaScript?
4. If this repository does not own an affected runtime, stop with `TRIAGE.md`
naming the files checked, suspected runtime owner, resolved versions if
known, and required fixed versions `notebook 7.5.6+` and `jupyterlab 4.5.7+`.
5. Upgrade every controlled runtime:
- `notebook` to `7.5.6+`;
- `jupyterlab` to `4.5.7+`;
- `@jupyter-notebook/help-extension` to `7.5.6+`;
- `@jupyterlab/help-extension` to `4.5.7+`.
Regenerate locks, environment files, labextension metadata, image digests,
SBOMs, and rendered deployment manifests.
6. Add defense in depth for untrusted notebook contexts:
- set the JupyterLab sanitizer setting `allowCommandLinker` to `false`
where this repository controls defaults;
- disable the affected help extensions in temporary containment images if
an upgrade cannot be deployed atomically;
- make uploaded or agent-generated notebooks open in a lower-trust
workspace without user secrets, terminals, or privileged kernels;
- ensure tokens are not embedded in shareable URLs or logs.
7. Add safe regression checks:
- dependency or lockfile assertions for the fixed package versions;
- image/version probes for Notebook and JupyterLab;
- config tests proving `allowCommandLinker` is false in untrusted notebook
profiles;
- static sanitizer tests using inert fixture strings, not live exploit
notebooks and not real tokens;
- deployment render checks proving patched images or containment settings
are present.
8. Add operator containment for non-atomic rollouts:
- temporarily block untrusted notebook uploads or previews;
- disable terminals for high-risk shared notebook pools if feasible;
- restart vulnerable notebook servers after patched images roll out;
- invalidate active browser sessions or Jupyter tokens where exposure was
plausible;
- preserve logs needed to review suspicious API, file, kernel, and terminal
activity.
9. Add a PR body section named `CVE-2026-40171 operator actions` that states:
- Notebook, JupyterLab, and help-extension versions before and after the
change;
- which notebook workspaces could open untrusted notebooks or Markdown;
- whether command linker remains enabled anywhere and why;
- whether tokens, sessions, kernels, terminals, datasets, model artifacts,
or workspace files may have been exposed;
- which sessions or tokens should be invalidated;
- which logs should be reviewed for file reads, file writes, kernel
execution, terminal creation, or unexpected REST API use.
10. Run relevant validation: package-manager install, lockfile consistency,
unit tests, frontend tests, image build, Jupyter startup/version checks,
deployment rendering, SBOM refresh, dependency/security scans, and any
notebook workspace smoke tests available in this repository.
11. Use PR title:
`fix(sec): remediate CVE-2026-40171 in Jupyter workspaces`.
## Stop conditions
- No affected Jupyter runtime, image, extension bundle, or workspace template
is controlled by this repository.
- A fixed Jupyter version cannot be consumed without a broader notebook
platform migration.
- The only available verification would require opening a weaponized notebook
or extracting a real token.
- Product requirements intentionally require command-linker execution inside
untrusted notebooks; document the risk and require a product/security
decision.
- Validation fails for unrelated pre-existing reasons; document those failures
instead of broadening scope.Verification - what the reviewer looks for
- No controlled Python lock, Conda environment, npm lock, labextension bundle, image, SBOM, or deployment target resolves vulnerable Notebook, JupyterLab, or help-extension versions.
- Untrusted notebook profiles disable command linker or run in a reduced-trust workspace without privileged kernels, terminals, user secrets, or broad file mounts.
- Tests prove the fixed versions and sanitizer defaults without creating a live exploit notebook or exposing a real token.
- Operator actions cover session/token invalidation and log review when vulnerable users could have opened untrusted notebooks.
- The PR does not contain notebook cells, screenshots, logs, or fixtures with real tokens, cookies, files, kernel output, terminal output, or secrets.
Watch for
- Updating
requirements.txtwhile Conda envs, Docker layers, JupyterHub single-user images, devcontainers, or labextension bundles still ship the vulnerable frontend. - Treating an authenticated-only notebook server as safe when the attack depends on a signed-in user opening untrusted notebook content.
- Fixing JupyterLab while leaving Notebook 7.x images, workspace templates, or CI notebook renderers vulnerable.
- Keeping command linker enabled in agent-generated notebook previews where model output can become clickable UI.
- Logging token-bearing URLs or REST requests while adding diagnostics.
References
- GitHub Advisory Database: https://github.com/advisories/GHSA-rch3-82jr-f9w9
- JupyterLab command-linker documentation: https://jupyterlab.readthedocs.io/en/latest/user/commands.html#commands-in-markdown-output-and-files