All vulnerabilities
CVE-2026-111058GHSA-rv4m-xm3f-3ccq

Mercury: Unauthenticated Remote Code Execution via /api/kernels

mljar mercurypipLibraries & packages
CVSS
9.8Critical
ExploitationNo known exploitationNot in CISA KEV, which does not prove it is unexploitedCISA KEV
Exploit odds (EPSS)0.44%Chance of exploitation activity in the next 30 days, higher than 37% of CVEs. Scored 23 Oct 2026FIRST EPSS
Fixed in3.2.6Fixed versionGitHub
Published19 Oct 2026Updated 19 Oct 2026CVE List

What fixes it

  • 3.2.6mercury, pipGitHub
  • 3.2.6mercury, PyPIOSVpip install "mercury>=3.2.6"

A fixed version on one release line is not the upgrade target for every line. Check your exact version and any vendor backports.

Description

Mercury runs a JupyterLab server with anonymous access by default (mercury_app/__main__.py sets --IdentityProvider.token='' when no --token/MERCURY_TOKEN is given; when tokenless it also sets --ServerApp.disable_check_xsrf=True). It relies on a blocklist (mercury_app/block_handler.py BLOCKED_PATTERNS: /lab, /api/terminals, /api/shutdown, /files) to keep anonymous users off dangerous Jupyter endpoints.

The vulnerability

/api/kernels is NOT in the blocklist (and cannot be — Mercury needs kernels to run notebooks), and patch_kernel_websocket_handler() (mercury_app/idle_timeout.py) only tracks the idle-timeout: it wraps on_message to call self.application._timeout_manager.touch() and then invokes the original handler with **no filtering of execute_request**. So any unauthenticated network client can:

POST /api/kernels {"name":"python3"}        -> 201, returns kernel id
open websocket /api/kernels/<id>/channels
send an execute_request with arbitrary code -> arbitrary Python execution = RCE

Distinct from GHSA-f8c7-rwf9-fmgm (incomplete fix)

GHSA-f8c7 was "Unauthenticated RCE via /api/terminals" — a missing-comma blocklist bypass. Its fix (add the comma so /api/terminals is blocked) does NOT address /api/kernels, which remains exploitable. The blocklist approach is fundamentally unable to cover kernels, so this is not a variant that another blocklist entry fixes.

Runtime-proven (on the patched version)

On mercury 3.2.4 — the release that fixed GHSA-f8c7 — with the default (tokenless) config, as an unauthenticated client: POST /api/terminals returns 403 (the f8c7 fix is present), but POST /api/kernels returns 201; opening the kernel websocket and sending an execute_request executed attacker-supplied Python (ran whoami as the server process user and wrote a marker file /tmp/PWNED_MERCURY_RCE). Full unauthenticated remote code execution. Deterministic PoC (client script + notebook) included.

Impact

Unauthenticated, network-reachable arbitrary code execution as the Mercury server process user on every default deployment — complete compromise of the host/container and any data/secrets it can reach.

Fix

The blocklist cannot secure an anonymous kernel-backed server. Require real per-request authentication (a token or password) by default, or restrict the kernel message channel so anonymous websocket clients cannot issue execute_request outside Mercury's own controlled execution flow.

Dedup (3-method)

OSV.dev CLEAN(0) for mercury and mljar-mercury; the repo's only advisory (GHSA-f8c7-rwf9-fmgm) covers /api/terminals only (description does not mention kernels); no issue/PR describes the /api/kernels RCE (#219/#134/#262 are "add auth" feature requests that merely confirm anonymous-by-default). Sink independently confirmed on current HEAD (blocklist omits /api/kernels; token='' default; patch_kernel_websocket_handler does no execute filtering).

Finder: Abdullah Kareem (GitHub: CyberKareem).

Text from GitHub Advisory Database

Affected versions 53

  • mercury, pip<= 3.2.5GitHub
  • mercuryaffected: < 3.2.6CVE List
  • mercury, PyPIfrom first release, fixed in 3.2.6OSV
  • mercury, PyPI1.1.6OSV
  • mercury, PyPI1.99.0OSV
  • mercury, PyPI1.99.1OSV
  • mercury, PyPI1.99.10OSV
  • mercury, PyPI1.99.2OSV
  • mercury, PyPI1.99.3OSV
  • mercury, PyPI1.99.4OSV
  • mercury, PyPI1.99.5OSV
  • mercury, PyPI1.99.6OSV
  • mercury, PyPI1.99.7OSV
  • mercury, PyPI1.99.8OSV
  • mercury, PyPI1.99.9OSV
  • mercury, PyPI2.0.0OSV
  • mercury, PyPI2.0.1OSV
  • mercury, PyPI2.0.10OSV
  • mercury, PyPI2.0.11OSV
  • mercury, PyPI2.0.12OSV
  • mercury, PyPI2.0.2OSV
  • mercury, PyPI2.0.3OSV
  • mercury, PyPI2.0.4OSV
  • mercury, PyPI2.0.5OSV
  • mercury, PyPI2.0.6OSV
  • mercury, PyPI2.0.7OSV
  • mercury, PyPI2.0.8OSV
  • mercury, PyPI2.0.9OSV
  • mercury, PyPI2.1.0OSV
  • mercury, PyPI2.1.1OSV
  • mercury, PyPI2.1.2OSV
  • mercury, PyPI2.1.3OSV
  • mercury, PyPI2.1.4OSV
  • mercury, PyPI2.1.5OSV
  • mercury, PyPI2.1.6OSV
  • mercury, PyPI2.1.7OSV
  • mercury, PyPI2.1.8OSV
  • mercury, PyPI2.1.9OSV
  • mercury, PyPI2.2.0OSV
  • mercury, PyPI2.2.1OSV
  • mercury, PyPI2.2.2OSV
  • mercury, PyPI2.2.3OSV
  • mercury, PyPI2.2.4OSV
  • mercury, PyPI2.2.5OSV
  • mercury, PyPI2.2.6OSV
  • mercury, PyPI2.2.7OSV
  • mercury, PyPI2.2.8OSV
  • mercury, PyPI2.2.9OSV
  • mercury, PyPI2.3.0OSV
  • mercury, PyPI2.3.1OSV
  • mercury, PyPI2.3.10OSV
  • mercury, PyPI2.3.2OSV
  • mercury, PyPI2.3.3OSV

References 4