Skip to main content
Mallory
CriticalCISA KEVExploited in the wildPublic exploit

Pre-Auth RCE in Marimo /terminal/ws WebSocket Endpoint

IdentifiersCVE-2026-39987CWE-306· Missing Authentication for…Also known asghsa_2679_6mx9_h9xc

CVE-2026-39987 is a critical pre-authentication remote code execution vulnerability in marimo, the reactive Python notebook platform. In versions prior to 0.23.0, the terminal WebSocket endpoint at /terminal/ws accepts connections without enforcing authentication. Unlike other WebSocket routes such as /ws that invoke validate_auth(), the /terminal/ws handler only checks runtime mode and PTY/platform support before accepting the connection, then exposes a PTY-backed shell. As a result, an unauthenticated remote attacker can complete a single WebSocket handshake to /terminal/ws and obtain an interactive shell capable of executing arbitrary system commands on the host with the privileges of the marimo process.

Share:
For your environment

Are you exposed to this one?

Mallory correlates every CVE against your assets, your vendors, and active adversary campaigns. Know which vulnerabilities matter for you, not just which ones are loud.

ANALYST BRIEF

Impact, mitigation & remediation

What it means. What to do now. Patch path, mitigations, and the assume-compromise checklist.

Impact

What an attacker gets, and what they’ve been doing with it.

Successful exploitation gives an unauthenticated attacker immediate interactive shell access on the target system and arbitrary command execution as the marimo service account. On exposed deployments this can lead to full system compromise, theft of notebooks, environment variables, API keys, cloud credentials, SSH keys, database credentials, and other secrets, followed by persistence, malware deployment, and lateral movement to internal services such as PostgreSQL and Redis. Where marimo runs as root, including common default containerized deployments, impact can extend to full root-level host or container compromise.

Mitigation

If you can’t patch tonight, do this now.

If immediate patching is not possible, prevent untrusted network access to marimo, especially the /terminal/ws endpoint. Restrict edit-mode instances to trusted administrators only, avoid binding to 0.0.0.0 on untrusted networks, place the service behind a VPN or authenticated reverse proxy, or disable/restrict terminal functionality where feasible. Run marimo as a non-root user, minimize container privileges, audit and reduce secrets present on the host, and monitor for suspicious WebSocket connections to /terminal/ws and shell-spawning activity. Treat previously exposed instances as potentially compromised.

Remediation

Patch, then assume compromise.

Upgrade marimo to version 0.23.0 or later, which fixes the issue by enforcing authentication on the /terminal/ws endpoint. Identify all internet-exposed or otherwise reachable marimo instances and patch them immediately. After patching, review exposed systems for signs of compromise and rotate any credentials or secrets that may have been accessible from the notebook host, including cloud keys, API tokens, SSH keys, database passwords, and environment-file secrets.
PUBLIC EXPLOITS

Exploits

7 valid exploits after Mallory filtered fakes, detection scripts, and README-only repos (5 hidden).

VALID 7 / 12 TOTALView more in app
CVE-2026-39987-POCMaturityPoCVerified exploit

This repository is a small standalone Python exploit PoC for CVE-2026-39987, described as a pre-authentication remote code execution issue affecting Marimo versions earlier than 0.23.0. The repository contains one substantive code file (CVE-2026-39987.py), plus a README, dependency list, license, and an auxiliary Dork.txt file with internet-search fingerprints. The main exploit flow is straightforward: it normalizes the supplied target URL, optionally probes /favicon.ico and /api/version to confirm the application and extract a version string, then builds a WebSocket URL to /terminal/ws using ws:// or wss:// depending on the original scheme. If the target appears vulnerable or the operator uses --no-check, the script connects to the terminal WebSocket and attempts to execute attacker-supplied commands. Based on the README and visible code structure, it supports three operator modes: single command execution, pseudo-interactive shell access, and generated reverse shell execution. Notable exploit capabilities include unauthenticated command execution, interactive terminal-style access, and reverse shell payload generation using operator-provided callback IP and port. SSL certificate validation is explicitly disabled for HTTPS/WSS targets, improving compatibility against self-signed deployments. The script also includes dependency checks and user-facing CLI argument parsing, indicating it is intended for direct operational use rather than just demonstrating a minimal bug trigger. Fingerprintable target endpoints are concentrated around /api/version, /favicon.ico, and especially /terminal/ws, which is the exploitation path. The Dork.txt file is auxiliary reconnaissance material and contains multiple Shodan/FOFA/Censys search fingerprints; however, most of those appear generic and not specific to Marimo. Overall, this is a real exploit PoC rather than a detector, and its maturity is best classified as OPERATIONAL because it includes practical exploitation logic and payload support, but not a broader framework or highly modular payload system.

M3PH1569Disclosed May 24, 2026pythontextwebnetwork
CVE-2026-39987-marimo-rceMaturityPoCVerified exploit

This repository is a small standalone proof-of-concept exploit for CVE-2026-39987, described here as a pre-authentication remote code execution issue in Marimo versions prior to 0.23.0. The main exploit is CVE-2026-39987-poc.py, a Python script using the websocket-client library. It accepts a target URL and an arbitrary command, converts http/https targets into ws/wss, connects to the target WebSocket terminal endpoint at /terminal/ws, drains initial PTY output, sends the supplied command with a newline, and prints returned output until timeout or marker text. Its core capability is unauthenticated remote command execution through an exposed terminal WebSocket, effectively yielding shell-like access with the privileges of the Marimo process. Repository structure is minimal: one Python exploit, a README documenting the vulnerability and usage, and a docker-vulnerable lab containing a Dockerfile and docker-compose.yml. The Docker lab installs marimo==0.22.3, exposes port 2718, binds to 0.0.0.0, and disables authentication/token protections, creating a reproducible vulnerable environment. The exploit is not part of a larger framework and is operational rather than weaponized: it supports arbitrary operator-supplied commands but does not include advanced payload staging, persistence, or automation beyond command execution. Fingerprintable targets and observables include the /terminal/ws endpoint, TCP port 2718, host binding 0.0.0.0, and filesystem paths used in examples and the lab such as /app/notebooks, /etc/passwd, /etc/os-release, and /root/.bash_history. Overall, the repository’s purpose is to demonstrate and validate unauthenticated WebSocket terminal access leading to RCE against vulnerable Marimo deployments.

0xdeadrootDisclosed May 16, 2026pythondockerfilenetworkweb
CVE-2026-39987-LabMaturityPoCVerified exploit

This repository is a local Docker lab and exploit demonstration for CVE-2026-39987, a pre-authentication RCE in marimo’s terminal WebSocket endpoint /terminal/ws. The repo contains two containerized environments: a vulnerable marimo 0.20.4 instance under vuln/ and a patched marimo 0.23.0 instance under patched/, both launched with marimo edit in headless mode on container port 2718 and exposed locally as 127.0.0.1:8081 and 127.0.0.1:8082. The notebook files are minimal and exist only to start the marimo edit server. The exploit logic is in poc/poc.py and poc/rce_poc.py. poc.py is a constrained proof-of-execution script: it validates that the supplied base URL is localhost-only, converts it to a WebSocket URL ending in /terminal/ws, connects without authentication, sends a benign shell command sequence (id; whoami; hostname) bracketed by markers, receives PTY output, strips ANSI/control noise, and reports vulnerability if uid= appears in the captured output. This is a real exploit path because it performs unauthenticated command execution, not just detection. poc/rce_poc.py is a less restricted interactive client that connects to the same endpoint and provides an operator-driven shell-like interface over the WebSocket, making it more capable than the benign PoC. Repository structure is straightforward: docker-compose.yml orchestrates both services with localhost-only bindings and container hardening; vuln/ and patched/ each contain a Dockerfile and notebook; poc/ contains the exploit scripts and Python dependencies; README.md documents the vulnerability, setup, and expected behavior; SAFETY.md defines local-only guardrails. Overall, the repository’s purpose is to compare vulnerable versus patched behavior and demonstrate that unauthenticated access to /terminal/ws can yield command execution as the marimo process user.

rootdirective-secDisclosed May 4, 2026pythonyamlwebnetwork
CVE-2026-39987-lab-or-marimo-cve-labMaturityPoCVerified exploit

This repository is a small self-contained exploit lab for CVE-2026-39987 affecting marimo. It contains four files: a Python exploit (`exploit.py`), a vulnerable target container definition (`Dockerfile.target`), a Docker Compose lab environment (`docker-compose.yml`), and a detailed walkthrough (`README.md`). The overall purpose is to reproduce and study a pre-authentication remote code execution condition caused by an authentication bypass on marimo's terminal WebSocket endpoint. The main exploit capability is in `exploit.py`. It connects directly to a user-supplied WebSocket URL, intended to be `ws://<target>:2718/terminal/ws`, using the `websocket-client` library. After connecting, it drains any initial PTY/banner output, then either: (1) sends a single shell command and returns the output (`exec` mode), or (2) provides an interactive shell loop (`shell` mode). The exploit does not perform authentication, token handling, or session negotiation; it relies entirely on the vulnerable endpoint accepting the WebSocket connection unauthenticated. Output parsing is basic but functional: it reads until timeout or until a shell prompt ending in `#` or `$` is observed. The target environment is intentionally configured to demonstrate impact clearly. `Dockerfile.target` installs `marimo==0.20.4`, creates a notebook directory under `/app/notebooks`, exposes TCP port 2718, and launches `marimo edit --host 0.0.0.0 --port 2718 --token .`. `docker-compose.yml` publishes port 2718 to the host and explicitly runs the target container as root, so successful exploitation yields root-level command execution inside the container. The README explains the vulnerability model: normal endpoints such as `/` and `/ws` enforce authentication, but `/terminal/ws` allegedly accepts WebSocket connections without validating auth when marimo is in edit mode and terminal support is enabled. The exploit therefore targets a web/network attack surface, specifically an unauthenticated WebSocket endpoint. This is a real exploit PoC rather than a detector: it provides direct command execution and an interactive shell, making it operational but not heavily weaponized.

Dhiaelhak-RachedDisclosed Apr 26, 2026pythonyamlwebnetwork
CVE-2026-39987MaturityPoCVerified exploit

This repository is a standalone Python exploit tool for CVE-2026-39987, described as an unauthenticated WebSocket pre-auth RCE in Marimo versions prior to 0.23.0. The repository is small and simple: one main Python script (CVE-2026-39987.py), a README with usage and vulnerability details, and a license file. No external exploit framework is used. The main script is an operational mass scanner/exploitation utility rather than a minimal proof of concept. It imports websockets, requests, asyncio, threading, and rich, indicating concurrent network exploitation with formatted console output. The code defines output artifacts under nx_output/ and uses worker threads to process many targets concurrently. Based on the visible constants and README, the exploit connects to the vulnerable /terminal/ws endpoint over ws:// or wss:// to obtain a PTY shell without authentication. Beyond initial shell access, the script contains environment profiles for multiple deployment types including Marimo, cPanel, Plesk, Apache, Nginx, and Python app environments. These profiles enumerate likely web roots, config directories, log locations, and credential files. The exploit appears designed to run post-compromise discovery commands through the shell to identify privilege level, enumerate notebooks and users, inspect SSH/config/log files, harvest tokens and credentials, and probe for databases. It also attempts a proof-of-write/web verification step by dropping a marker file such as Nx.py or Nx.php into likely web roots and then checking HTTP-accessible paths like /Nx.php or /api/files/Nx.py for the string "Nxploited". Fingerprintable targets and paths are abundant in the code: the primary network target is /terminal/ws, while many filesystem paths are hardcoded for enumeration and credential access, including /root/.my.cnf, /etc/mysql/debian.cnf, /etc/psa/.psa.shadow, /etc/apache2, /etc/nginx, /var/log/nginx, /var/log/apache2, /var/www/html, and /etc/shadow. The README also documents example target formats and the common Marimo port 2718. Overall, this is a real exploit repository with offensive capability: it provides unauthenticated remote command execution against vulnerable Marimo instances and automates extensive host discovery and data collection after access is obtained.

NxploitedDisclosed Apr 18, 2026pythonmarkdownnetworkweb
CVE-2026-39987_exploitMaturityPoCVerified exploit

Repository contains three Python utilities, one README, and one HTML helper page. The core purpose is exploitation of an alleged Marimo pre-auth remote code execution issue via unauthenticated WebSocket access to /terminal/ws on port 2718. CVE-2026-39987_exploit.py is a simple interactive exploit that opens a ws:// or wss:// connection and forwards stdin/stdout for shell-like interaction. CVE-2026-39987_scanner.py is a more aggressive probe script that connects to the same endpoint and sends hardcoded commands to confirm execution, including sensitive file reads. exploit_fast.py is the most feature-rich implementation: it optionally checks /api/version, compares versions against <0.23.0, supports single-command execution, interactive mode, and reverse-shell payload generation. The payload format in exploit_fast.py differs from the simpler exploit/scanner by sending JSON objects with type=exec and command fields, suggesting either multiple protocol assumptions or inconsistent understanding of the target protocol. website.html appears to be a local command-reference UI rather than exploit logic. Overall, this is a standalone Python exploit repository, not tied to a major framework. It is operational because it includes working exploit routines and payload generation, but payload customization is basic and mostly operator-supplied. The repository also shows internal inconsistency in claimed affected versions (README says <=0.20.4 while exploit_fast.py checks <0.23.0), which reduces confidence in targeting accuracy.

mki9Disclosed Apr 13, 2026pythonhtmlwebnetwork
marimo_CVE-2026-39987_RCE_PoCMaturityPoCFrameworknucleiVerified exploit

Repository contains a Python proof-of-concept exploit and a Nuclei template for CVE-2026-39987, targeting Marimo versions earlier than 0.23.0. The main exploit script, CVE-2026-39987_PoC.py, performs optional passive checks against /favicon.ico and /api/version, then converts the supplied base URL into a ws:// or wss:// connection to /terminal/ws and uses that unauthenticated terminal WebSocket to execute attacker-supplied commands. The script supports three main modes: one-shot command execution, interactive shell mode, and reverse shell generation using an operator-supplied callback IP and port. SSL verification is disabled for HTTPS targets, and the script includes basic operator prompts and dependency checks. The repository also includes CVE-2026-39987_nuclei.yaml, which is a detection template rather than an exploit; it fingerprints Marimo via favicon hash -1864630356, extracts the version from /api/version, and checks whether /terminal/ws responds as a WebSocket endpoint. Supporting files include README.md with usage examples, impact notes, remediation guidance, and example commands, plus requirements.txt and a short installation/usage note. Overall, this is a functional operational PoC for unauthenticated remote command execution against exposed vulnerable Marimo instances, accompanied by a scanner template for identification.

fevar54Disclosed Apr 13, 2026pythonyamlwebnetwork
EXPOSURE SURFACE

Affected products & vendors

Products and vendors Mallory has correlated with this vulnerability. Open in Mallory to drill down to specific CPE configurations and version ranges.

VendorProductType
CoreWeaveMarimoapplication

Vendor-confirmed product mapping. Mallory continuously reconciles this list against your asset inventory.

What this page doesn’t show

The version that knows your environment.

This page is what’s public. Mallory adds the parts that aren’t: which of your assets are affected, which adversaries are exploiting it right now, which detections to deploy, and what to do tonight.
Exposure mapping

Query your assets running an affected version, and investigate the blast radius.

Threat actor evidence

Every observed campaign linking this CVE to a named adversary.

Associated malware6

Malware families riding this exploit, with evidence and IOCs.

Detection signatures1

YARA, Sigma, Snort, and vendor rules, auto-deployed to your SIEM.

Vendor-by-vendor mapping

Cross-references every affected SKU, including bundled OEM variants.

Social activity123

Community discussion across Reddit, Mastodon, and other social sources.