---
id: "CVE-2026-111058"
kind: "vulnerability"
aliases: ["CVE-2026-111058", "GHSA-rv4m-xm3f-3ccq"]
title: "Mercury: Unauthenticated Remote Code Execution via /api/kernels"
severity: "critical"
cvss: 9.800000190734863
epss: 0.004370000213384628
exploited: false
status: "open"
category: "package"
products: [{"name": "mercury", "fixed": ["3.2.6"], "affected": "<= 3.2.5", "ecosystem": "pypi"}]
ecosystems: ["pypi"]
tags: ["cwe-862", "jupyter", "mercury", "package", "python", "self-hosted"]
not_affected_if: ["auth-token-set", "not-network-exposed", "version-3.2.6-or-later"]
published_at: "2026-10-19T16:17:03+00:00"
first_seen_at: "2026-10-23T19:11:32+00:00"
updated_at: "2026-10-23T21:57:18+00:00"
sources: [{"source": "ghsa", "url": "https://github.com/advisories/GHSA-rv4m-xm3f-3ccq", "first_seen_at": "2026-10-23T19:11:32+00:00"}, {"source": "nvd", "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-111058", "first_seen_at": "2026-10-23T21:57:18+00:00"}]
---

# Mercury: Unauthenticated Remote Code Execution via /api/kernels

Mercury (the mljar Python package) runs a JupyterLab server that is anonymous by default and blocks only a few endpoints, leaving /api/kernels reachable. An unauthenticated network client can start a kernel, send an execute_request over websocket, and run arbitrary Python as the server process user.

_Summary, check and fix written by a model from the sources; labelled as such._

## Affected

- pypi:mercury affected <= 3.2.5 fixed 3.2.6

## How to check

Check the installed version with pip show mercury; versions 3.2.5 and below are affected. Look for mercury being started without --token or MERCURY_TOKEN set; that is the default-config case.

## Fix

Upgrade mercury to 3.2.6 or later, per the advisory's fixed version.
If you cannot upgrade, set a token (--token or MERCURY_TOKEN) so anonymous access is disabled, and keep the server off untrusted networks.

## Timeline

- 2026-10-23T19:11:32+00:00 ghsa https://github.com/advisories/GHSA-rv4m-xm3f-3ccq
- 2026-10-23T21:57:18+00:00 nvd https://nvd.nist.gov/vuln/detail/CVE-2026-111058

## From the sources

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).

---

_Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai_
