Software Supply Chain Security Advisory · Python Ecosystem
CVE-2026-39987 9.3 CRITICAL

Marimo RCE Flaw
Weaponized in 10 Hours

A zero-authentication terminal WebSocket in a popular Python notebook framework handed attackers a full shell — and they used it before most defenders even read the advisory.

CLASSIFICATION PUBLIC ADVISORY SEVERITY CRITICAL VECTOR PRE-AUTH WEBSOCKET RCE
9.3
CVSS v4.0 Score
<10h
Disclosure to Exploit
19.6k
GitHub Stars
0
Auth Required
Executive Summary ACTIVELY EXPLOITED IN THE WILD
What Happened

A critical missing authentication check in Marimo's terminal WebSocket endpoint (/terminal/ws) allowed any attacker on the internet to obtain a full interactive shell — no credentials, no exploit code needed.

Why It Matters

Marimo is used by data science, ML, and analytics teams — environments rich with cloud credentials, SSH keys, API tokens, and sensitive notebooks. One unauthenticated connection = full system access.

Immediate Risk Level

Any internet-reachable Marimo instance running version 0.22.5 or earlier should be treated as fully compromised. Upgrade to 0.23.0 immediately and audit for credential exfiltration.

Vulnerable Versions - Python Ecosystem
All Versions Up To marimo ≤ 0.22.5 Vulnerable
Endpoint Affected /terminal/ws No Auth Check
Default Port TCP 2718 Internet Exposed
Attack Complexity NONE Trivial to Exploit
Patched Version: marimo 0.23.0 — Recommended to upgrade to this version

Marimo is a modern open-source Python notebook framework — a reactive alternative to Jupyter used widely by data science, machine learning, and analytics teams. With nearly 20,000 GitHub stars, it has become a trusted tool for running and sharing Python-based analyses, often deployed in cloud containers where team members can collaborate over the network.

On April 8, 2026, Marimo's maintainers published a security advisory for CVE-2026-39987, a critical pre-authentication remote code execution vulnerability. The flaw exists in the application's integrated terminal feature: a WebSocket endpoint at /terminal/ws that provides a fully interactive command-line shell to connected users — except it never checks whether the connecting party is actually authorized.

Unlike every other WebSocket endpoint in Marimo, which correctly calls an authentication validation function before accepting connections, the terminal endpoint skipped this check entirely. Any attacker who could reach the server over the network could simply open a WebSocket connection and immediately receive a full PTY (pseudo-terminal) shell running as the Marimo process user.

The Authentication Asymmetry

Marimo uses Starlette's AuthenticationMiddleware, which marks unauthenticated users but does not actively block WebSocket connections — enforcement depends on @requires() decorators or explicit validate_auth() calls. The /terminal/ws endpoint had neither. The /ws endpoint on the same server correctly called validate_auth(). One line of missing code created a critical security gap.

April 8, 2026 — Advisory Published
Disclosure: Marimo maintainers publish the security advisory for CVE-2026-39987 with full technical details, including the affected endpoint and the nature of the authentication bypass. No PoC was released.
T + 9 Hours 41 Minutes
First attack observed: An unknown threat actor connects to the /terminal/ws WebSocket on Sysdig's honeypot. Manual reconnaissance begins — the attacker explores the file system to understand the environment.
T + Minutes Later
Credential harvesting: The attacker systematically targets .env files, searches for SSH keys, and reads various configuration files. The operation is manual, deliberate, and focused purely on credential theft.
T + ~1 Hour After Initial Entry
Return visit: The attacker reconnects to the honeypot, re-reads the .env file contents, and — notably — checks whether any other threat actors had accessed the system in the interim.
No Malware Deployed
Targeted operation: No cryptocurrency miners, backdoors, or ransomware were installed. This was a focused intelligence-gathering and credential theft operation — suggesting a sophisticated actor with specific targets in mind.

The vulnerability originates in marimo/_server/api/endpoints/terminal.py at lines 340–356, where websocket.accept() is called without any prior authentication. The terminal endpoint only checks two conditions before granting shell access: whether the server is in the correct running mode, and whether the platform supports terminal functionality. No user identity check. No token validation.

Vulnerable Code Pattern — terminal.py (simplified)
# /terminal/ws endpoint — VULNERABLE
async def terminal_ws(websocket: WebSocket):
    # Only checks mode + platform — NO auth validation
    if running_mode == "edit" and platform_supports_terminal:
        await websocket.accept()  # ← Full PTY shell granted immediately

# /ws endpoint — SECURE (for comparison)
async def ws_endpoint(websocket: WebSocket):
    await WebSocketConnectionValidator.validate_auth(websocket) # ← Auth enforced
    await websocket.accept()

The exploit is as simple as it gets: open a WebSocket handshake to the target's /terminal/ws endpoint. The advisory itself documented a complete working path. No specialized tooling required — any WebSocket client, including common browser developer tools, can execute the attack.

In default Docker deployments, the Marimo process typically runs as root, meaning exploitation yields unrestricted system-level access. The attacker runs as the most privileged user on the container or host from the moment of connection.

Why Data Science Environments Are High-Value Targets

Notebook servers like Marimo are deployed in environments that are intentionally rich in sensitive data: cloud provider API keys in .env files, AWS/GCP/Azure credentials, SSH keys for accessing production systems, database connection strings, ML model weights, and proprietary datasets. A single unauthenticated shell on a Marimo instance can yield credentials that provide lateral movement across an entire cloud infrastructure.

Scope of Exposure

Marimo's default server port is TCP 2718. Research indicates that while direct internet listeners are limited in large-scale scans, the real exposure is in cloud-hosted notebooks, internal platforms without network segmentation, and Kubernetes clusters where Marimo is exposed to shared networks. Any instance reachable by an attacker — even via a lateral movement path — is fully exploitable without credentials.

For leadership teams, the key framing is that developer and data science tooling has historically received less security scrutiny than customer-facing infrastructure — yet it sits at the intersection of source code, cloud access, and sensitive business data. This incident demonstrates that gap is actively exploited.

Immediate Risk

Full Credential Exfiltration

Cloud keys, database passwords, API tokens, and SSH keys in notebook environments should be assumed stolen if the instance was internet-reachable during the exposure window.

Lateral Movement

Cloud Infrastructure Access

Notebook hosts typically reach databases, object stores, internal HTTP services, and peer systems. Stolen credentials enable attackers to pivot from a notebook server to production cloud infrastructure.

Data Risk

Sensitive Notebooks & Models

Proprietary ML models, training datasets, business logic embedded in notebooks, and analytical outputs may be exfiltrated or tampered with silently.

Persistent Access

Backdoor Potential

While this attacker chose not to install persistence mechanisms, the open shell access enables any form of follow-on activity — miners, backdoors, ransomware — at the attacker's discretion.

Risk Area Severity Description
Pre-Auth RCE Critical Zero authentication required. Any attacker who can reach the port gets an immediate interactive shell. Attack complexity is effectively none.
Credential Theft Critical Cloud API keys, SSH keys, .env secrets, and database passwords in notebook environments should be treated as fully compromised.
Root-Level Access Critical Default Docker deployments run Marimo as root. Exploitation yields the highest possible privilege level on the system immediately.
Speed of Exploitation Critical Under 10 hours from public disclosure to confirmed in-the-wild exploitation, with no PoC code available — built directly from the advisory text.
Cloud Lateral Movement Critical Notebook environments have high connectivity to cloud services. Credential theft from one Marimo instance can cascade across entire cloud accounts.
Detection Difficulty High Manual terminal access over WebSocket produces minimal default logging. Without dedicated endpoint detection, the attack may go unnoticed.
Patch Adoption Lag High Data science infrastructure is often not centrally managed like front-line web apps — patches may be applied slowly or inconsistently across teams.
Immediate Actions DO NOW
Upgrade to Marimo 0.23.0 immediately. All versions up to and including 0.22.5 are vulnerable. If you cannot patch, take the instance offline or firewall access to port 2718 entirely until the upgrade is complete.
Audit all internet-exposed Marimo instances. Check for any external access to port 2718 or WebSocket endpoints. Any instance reachable from outside your trusted network perimeter during the exposure window should be treated as compromised.
Rotate all credentials on affected systems: cloud API keys (AWS, GCP, Azure), SSH keys, database connection strings, .env secrets, and any tokens stored in notebooks or accessible from the server environment.
Review WebSocket access logs for unexpected connections to /terminal/ws. Look for sessions originating from IP addresses outside your organization's known ranges, especially around April 8–10, 2026.
Short-Term Hardening WITHIN 30 DAYS
Never expose notebook servers directly to the internet. Marimo, Jupyter, and similar tools should sit behind an authenticated reverse proxy or VPN. Treat them as internal development infrastructure, not public services.
Apply network segmentation to data science environments. Notebook servers should not have unrestricted access to production databases, cloud management APIs, or internal services. Least-privilege networking limits blast radius.
Do not run notebook containers as root. Configure Docker to run Marimo as a non-privileged user. This does not eliminate the RCE risk but significantly reduces the impact of exploitation.
Enable runtime monitoring on notebook hosts to detect anomalous process spawning, unexpected outbound connections, and unusual file access patterns — the hallmarks of post-exploitation activity.
Long-Term Resilience ONGOING
Treat developer and data science tooling as part of your security perimeter. These tools hold privileged access to production systems and sensitive data. They deserve the same patch cadence and monitoring as front-line applications.
Subscribe to vulnerability feeds for all tools in your data stack — not just production web frameworks. GitHub Security Advisories, OSV, and tool-specific mailing lists provide early warning.
Audit WebSocket endpoints across all internal tooling for consistent authentication enforcement. The pattern here — one endpoint with auth, one without — is a common misconfiguration in rapidly developed open-source tools.
Assume a 24-hour exploitation window for any critical pre-auth RCE. When a new critical advisory drops, plan for active in-the-wild use on day one and patch faster than your mean time to read a CVE feed.
Vulnerability Details & Indicators
CVE ID
CVE-2026-39987
CVSS v4.0 Score
9.3 (Critical)
Affected Versions
marimo ≤ 0.22.5
Fixed Version
marimo 0.23.0
Vulnerable Endpoint
/terminal/ws
Default Port
TCP 2718
Authentication Required
None
Attack Complexity
Low (WebSocket handshake only)
Privileges Granted
Full PTY Shell (often root)
Time to First Exploitation
9 hours 41 minutes
GHSA ID
GHSA-2679-6mx9-h9xc
Disclosure Date
April 8, 2026
Vulnerable File
terminal.py lines 340–356