GHSA-RV4M-XM3F-3CCQ
Vulnerability from github – Published: 2026-10-19 16:49 – Updated: 2026-10-19 16:49Mercury 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).
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 3.2.5"
},
"package": {
"ecosystem": "PyPI",
"name": "mercury"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "3.2.6"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-111058"
],
"database_specific": {
"cwe_ids": [
"CWE-862"
],
"github_reviewed": true,
"github_reviewed_at": "2026-10-19T16:49:08Z",
"nvd_published_at": null,
"severity": "CRITICAL"
},
"details": "Mercury runs a JupyterLab server with **anonymous access by default** (`mercury_app/__main__.py` sets `--IdentityProvider.token=\u0027\u0027` 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.\n\n## The vulnerability\n`/api/kernels` is **NOT** in the blocklist (and cannot be \u2014 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:\n\n```\nPOST /api/kernels {\"name\":\"python3\"} -\u003e 201, returns kernel id\nopen websocket /api/kernels/\u003cid\u003e/channels\nsend an execute_request with arbitrary code -\u003e arbitrary Python execution = RCE\n```\n\n## Distinct from GHSA-f8c7-rwf9-fmgm (incomplete fix)\nGHSA-f8c7 was \"Unauthenticated RCE via `/api/terminals`\" \u2014 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.\n\n## Runtime-proven (on the patched version)\nOn **mercury 3.2.4** \u2014 the release that fixed GHSA-f8c7 \u2014 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.\n\n## Impact\nUnauthenticated, network-reachable arbitrary code execution as the Mercury server process user on every default deployment \u2014 complete compromise of the host/container and any data/secrets it can reach. \n\n## Fix\nThe 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\u0027s own controlled execution flow.\n\n## Dedup (3-method)\nOSV.dev CLEAN(0) for `mercury` and `mljar-mercury`; the repo\u0027s 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=\u0027\u0027` default; `patch_kernel_websocket_handler` does no execute filtering).\n\nFinder: Abdullah Kareem (GitHub: CyberKareem).",
"id": "GHSA-rv4m-xm3f-3ccq",
"modified": "2026-10-19T16:49:08Z",
"published": "2026-10-19T16:49:08Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/mljar/mercury/security/advisories/GHSA-rv4m-xm3f-3ccq"
},
{
"type": "WEB",
"url": "https://github.com/mljar/mercury/commit/73a40ceb0becf057f495a5738ad7f5a5222a53e1"
},
{
"type": "PACKAGE",
"url": "https://github.com/mljar/mercury"
},
{
"type": "WEB",
"url": "https://github.com/mljar/mercury/releases/tag/3.2.6"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "Mercury: Unauthenticated Remote Code Execution via /api/kernels"
}
Drag nodes to arrange them. Double-click a related vulnerability to open it, or a source to visit its link. The Physics button on the left tunes the layout and the simulation; the legend at the bottom left hides or shows nodes by kind and by sighting type.
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
Vulnerability timeline
Sightings and recorded dates, grouped by day · UTC
Loading timeline…
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.
Browse all ATT&CK techniques and the vulnerabilities related to each.
Related by attack behaviour
Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.