The Nine-Hour Window
On April 8, 2026, Marimo — a popular open-source Python notebook used by data scientists and ML engineers — published a security advisory for CVE-2026-39987: an unauthenticated remote code execution flaw in the notebook’s terminal WebSocket endpoint.
Less than half a day later, attackers were already in.
The Sysdig Threat Research Team, running honeypots seeded with exposed Marimo instances, logged the first in-the-wild exploitation attempt at 9 hours and 41 minutes after the advisory went public. Within roughly three minutes of the initial shell, the attacker had harvested credentials from the compromised environment.
There was no public proof-of-concept. There was no Metasploit module. There was only the advisory — and that, apparently, was enough.
How the Flaw Works
The vulnerability sits in Marimo’s terminal feature, which lets notebook users pop a shell inside their running Python environment. Under the hood, Marimo exposes this via a WebSocket endpoint at `/terminal/ws`.
The flaw is embarrassingly simple: every other sensitive WebSocket endpoint in Marimo calls `validate_auth()` before accepting connections. The `/terminal/ws` endpoint skipped it. It checked only the running mode and the platform, then handed any connecting client a full PTY (pseudo-terminal) shell running as whatever user launched Marimo.
In practice, that meant:
- Any Marimo instance reachable on the network (common in dev environments, cloud workstations, shared Jupyter-style platforms, and exposed homelabs) could be pre-auth compromised.
- The attacker got an interactive shell, not just a one-shot command primitive — ideal for manual reconnaissance, lateral movement, and data exfiltration.
- Because notebooks commonly hold API keys, cloud credentials, database connection strings, and training data, a shell in that context is often an immediate full-environment compromise.
CVE-2026-39987 carries a CVSS 9.3 score and affects all Marimo versions up to and including 0.20.4. It is fixed in 0.23.0.
The Attack Sequence
Sysdig’s telemetry painted a clinical picture of what a fresh, advisory-driven zero-day exploit looks like in 2026:
- T+0h — Marimo publishes the GitHub Security Advisory naming the vulnerable endpoint.
- T+~9h 41m — Attacker connects to the unauthenticated `/terminal/ws` endpoint on an exposed honeypot and lands a shell.
- T+9h 44m (~3 minutes after shell) — Attacker reads `.env`, `.aws/credentials`, `.bash_history`, and similar files. Credential harvesting complete.
- T+9h 44m to +11h 15m — Attacker reconnects four times over roughly 90 minutes, each session short and deliberate, consistent with a human operator working through a target list.
The attacker did not pivot aggressively or deploy ransomware in this specific observation. What matters is the speed and the method: a human read the advisory, wrote the exploit, scanned for targets, and was inside a compromised environment before most defenders had even filed the CVE in their tracker.
Advertisement
Why Developer Tools Are the Soft Underbelly
Marimo is not an isolated case. It fits a 2026 pattern:
- Developer tools run with privileged context. They hold source code, credentials, cloud tokens, pipeline secrets, and customer data samples.
- They are frequently internet-exposed. Cloud workspaces, hosted notebooks, CI runners, and collaborative IDEs often bind to 0.0.0.0 rather than localhost, and defenders rarely inventory them with the same rigor as production systems.
- Authentication is an afterthought. Tools designed for “local use” quietly become remote-accessible in cloud deployments, inheriting auth models that assume a trusted network.
- Patching cadence is slow. Data scientists and ML engineers upgrade notebooks far less frequently than security teams patch production infra.
Industry telemetry reinforces the urgency. Zero-day exploitation counts have climbed from 63 in 2022 to ~90 in 2025, and roughly 28% of exploited vulnerabilities are weaponized within 24 hours of disclosure. AI-assisted exploit development is compressing the window further — LLM-guided fuzzing tools are demonstrably speeding up both the discovery and weaponization phases.
CVE-2026-39987 is a case study for that compression. Nine hours. No PoC. Full pre-auth RCE.
What to Do — Right Now
If you run Marimo:
- Upgrade to version 0.23.0 or later immediately. This is non-negotiable if your instance is network-reachable.
- Audit for signs of compromise: unusual connections to `/terminal/ws`, unexpected shells spawned by the Marimo process, new SSH keys, credential files accessed, outbound traffic to unknown IPs.
- Bind Marimo to localhost (`–host 127.0.0.1`) wherever possible; use SSH port forwarding for remote access instead of exposing the notebook port.
- Rotate credentials that were reachable from any exposed pre-0.23.0 instance — cloud keys, database creds, git tokens.
If you run a data science or ML team:
- Inventory your notebook estate. Marimo, Jupyter, JupyterLab, Jupyter-AI, VS Code tunnels, Deepnote-style self-hosted tools — know what is deployed, where, and who owns it.
- Treat notebook servers as production systems. Patch SLAs. Authentication. Logging. Network segmentation. The “it’s just a dev tool” mental model is how attackers get free shells.
- Subscribe to advisories for the tools your team actually uses. Not just Windows and Linux CVEs — the long tail of Python/R/Julia/Rust developer tooling matters now.
The Larger Lesson
The takeaway from CVE-2026-39987 is not that Marimo is uniquely unsafe — the maintainers responded responsibly, shipped a fix, and documented the flaw transparently. The takeaway is that public disclosure itself is now a starting pistol. Attackers read advisories as eagerly as defenders do, and they often write exploits faster than patching programs can deploy fixes.
For any organization running open-source developer tools at scale, 2026’s working assumption should be simple: the window between “CVE published” and “actively exploited” is measured in hours, not weeks. Patching cadence, network exposure, and credential hygiene need to be designed around that reality — not around a nostalgic notion of how zero-day timelines used to work.
Frequently Asked Questions
Am I affected if I only run Marimo on localhost?
Risk is far lower if Marimo is bound to 127.0.0.1 and not exposed to any network. Still upgrade to 0.23.0, because local-only assumptions can silently break when someone runs the notebook inside a container, a cloud workstation, or a tunneled dev environment.
What should I check if I think a Marimo instance was compromised?
Look for connections to `/terminal/ws`, unexpected processes spawned by the Marimo parent, reads of `.env`, `.aws/credentials`, and `.bash_history`, new SSH keys, and outbound traffic to unfamiliar IPs. Rotate every credential that was accessible to the host.
Why are developer tools such frequent zero-day targets in 2026?
They combine privileged access (source code, cloud tokens, data) with weak authentication defaults and slow patching. Many are designed for local use but silently become remote-accessible in cloud deployments, making them a soft target for advisory-driven exploitation.
Sources & Further Reading
- Marimo OSS Python Notebook RCE: From Disclosure to Exploitation in Under 10 Hours — Sysdig
- Marimo RCE Flaw CVE-2026-39987 Exploited Within 10 Hours of Disclosure — The Hacker News
- Critical flaw in Marimo Python notebook exploited within 10 hours of disclosure — InfoWorld
- Critical Marimo Flaw Exploited Hours After Public Disclosure — SecurityWeek
- CVE-2026-39987 — Tenable
- Zero-Day Exploits Surge, 30% of Flaws Attacked Before Disclosure — Infosecurity Magazine






