Описание
Marimo: Pre-Auth Remote Code Execution via Terminal WebSocket Authentication Bypass
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:
Compare with the correctly implemented /ws endpoint (ws_endpoint.py lines 67-82):
Authentication 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
Reproduction Environment
Reproduction Result
With auth enabled (server generates random access_token), the exploit bypasses authentication entirely:
Suggested 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.
Ссылки
- https://github.com/marimo-team/marimo/security/advisories/GHSA-2679-6mx9-h9xc
- https://nvd.nist.gov/vuln/detail/CVE-2026-39987
- https://github.com/marimo-team/marimo/pull/9098
- https://github.com/marimo-team/marimo/commit/c24d4806398f30be6b12acd6c60d1d7c68cfd12a
- https://www.cisa.gov/known-exploited-vulnerabilities-catalog?field_cve=CVE-2025-39987
- https://www.cisa.gov/known-exploited-vulnerabilities-catalog?field_cve=CVE-2026-39987
- https://www.sysdig.com/blog/marimo-oss-python-notebook-rce-from-disclosure-to-exploitation-in-under-10-hours
Пакеты
marimo
< 0.23.0
0.23.0
EPSS
9.3 Critical
CVSS4
9.8 Critical
CVSS3
CVE ID
Дефекты
Связанные уязвимости
marimo is a reactive Python notebook. Prior to 0.23.0, Marimo 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. This vulnerability is fixed in 0.23.0.
Уязвимость функции validate_auth() фреймворка для работы с данными Marimo, позволяющая нарушителю повлиять на конфиденциальность, целостность и доступность информации
EPSS
9.3 Critical
CVSS4
9.8 Critical
CVSS3