Skip to content

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 notebook package is >=7.0.0, <=7.5.5.
  • Any resolved jupyterlab package is <=4.5.6.
  • Frontend bundles, labextension locks, or package manager metadata include vulnerable @jupyter-notebook/help-extension or @jupyterlab/help-extension versions.
  • 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.txt while 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