GHSA-rv4m-xm3f-3ccq: Critical severity pip/mercury vulnerability

Published Oct 19, 2026
·
Updated

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

Affected Software

1 affected componentFixes available
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. Configuration

    Require real per-request authentication by default; configure a non-empty IdentityProvider.token or MERCURY_TOKEN instead of the tokenless default.

    Mercury/JupyterLab IdentityProvider.token / MERCURY_TOKEN = non-empty token or password
  3. Compensating control

    Restrict the /api/kernels/<id>/channels kernel message channel so anonymous websocket clients cannot issue execute_request messages outside Mercury's controlled execution flow.

Event History

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

Frequently Asked Questions

1

Who is exposed to this issue?

Any Mercury deployment whose JupyterLab server is reachable by an unauthenticated network client is exposed when no --token option or MERCURY_TOKEN is configured. Mercury enables anonymous access by default in that situation.

2

What does an attacker need to exploit it?

The attacker needs only network access to the Mercury/JupyterLab server; no credentials or user interaction are required. They can create a Python kernel through /api/kernels, connect to its websocket channel, and submit an execute_request containing arbitrary code.

3

Are default deployments affected?

Yes. If Mercury is started without --token and without MERCURY_TOKEN, it explicitly configures an empty Jupyter identity token and disables XSRF checks. The existing blocklist does not block /api/kernels.

4

What version contains the fix?

The referenced Mercury release tag is 3.2.6. The advisory also references commit 73a40ceb0becf057f495a5738ad7f5a5222a53e1.

5

What can be done before patching?

Configure a non-empty token using --token or MERCURY_TOKEN and restrict network exposure so unauthenticated clients cannot reach the server. This prevents the anonymous access condition described by the advisory.

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