CVE-2026-111058: Mercury: Unauthenticated Remote Code Execution via /api/kernels

Published Oct 19, 2026
·
Updated

Mercury is a Python framework for sharing Jupyter notebooks as web applications and dashboards. Prior to 3.2.6, default tokenless deployments allow anonymous clients to create Jupyter kernels and send executerequest messages containing arbitrary Python. The endpoint blocklist does not cover /api/kernels, and the websocket wrapper previously tracked idle activity without authorizing executable messages. This issue is fixed in version 3.2.6.

Other sources

Mercury runs a JupyterLab server with anonymous access by default (mercuryapp/main.py sets --IdentityProvider.token='' when no --token/MERCURYTOKEN is given; when tokenless it also sets --ServerApp.disablecheckxsrf=True). It relies on a blocklist (mercuryapp/blockhandler.py BLOCKEDPATTERNS: /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 patchkernelwebsockethandler() (mercuryapp/idletimeout.py) only tracks the idle-timeout: it wraps onmessage to call self.application.timeoutmanager.touch() and then invokes the original handler with no filtering of executerequest. So any unauthenticated network client can:

POST /api/kernels {"name":"python3"} -> 201, returns kernel id open websocket /api/kernels/<id>/channels send an executerequest 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 executerequest executed attacker-supplied Python (ran whoami as the server process user and wrote a marker file /tmp/PWNEDMERCURYRCE). 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 executerequest 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; patchkernelwebsockethandler does no execute filtering).

Finder: Abdullah Kareem (GitHub: CyberKareem).

— GitHub

Affected Software

2 affected componentsFixes available
pypi/mercury<3.2.6
pip/mercury<=3.2.5
3.2.6

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade pip/mercury to a version that resolves this vulnerability.

    Fixed in 3.2.6
  2. Upgrade

    Upgrade mercury to a version that resolves this vulnerability.

    Fixed in 3.2.6
  3. Configuration

    Require real per-request authentication using a token or password by default; alternatively, restrict the kernel message channel so anonymous websocket clients cannot issue execute_request messages outside Mercury's controlled execution flow.

    Mercury authentication = token or password required by default

Event History

Oct 19, 2026
CVE Published
via MITRE·04:06 PM
Data Sourced
via MITRE·04:06 PM
DescriptionSeverityWeakness
Advisory Published
via GitHub·04:49 PM
Data Sourced
via GitHub·04:49 PM
DescriptionSeverityWeaknessAffected Software

Frequently Asked Questions

1

Which deployments are exposed?

Mercury deployments using the default tokenless configuration are exposed before version 3.2.6. Anonymous network clients can reach the affected Jupyter API endpoint.

2

What does an attacker need to exploit this issue?

An attacker needs only network access to the Mercury deployment. No authentication, privileges, or user interaction are required; they can create a Jupyter kernel through /api/kernels and send arbitrary Python in execute_request messages.

3

What is the immediate mitigation if upgrading is not possible?

Do not expose the affected tokenless deployment to anonymous clients. Restrict network access to trusted users or networks and require authentication so untrusted clients cannot access /api/kernels or send executable WebSocket messages.

4

How can I determine whether an instance is affected?

An instance is affected if it runs Mercury earlier than 3.2.6 and uses the default tokenless deployment configuration. The fixed version is 3.2.6.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203