AI Agent Post-Exploitation Is Real: Marimo CVE-2026-39987 and the 60-Minute Pivot Chain
On May 10, 2026 Sysdig recorded what looks like the first AI-agent-driven post-exploitation in the wild — Marimo CVE-2026-39987 to PostgreSQL exfiltration in under an hour, across 11 egress IPs. What it changes for defenders.
On 10 May 2026 the Sysdig Threat Research Team observed an intrusion they describe as "AI-agent-led" through the entire post-exploitation phase. An attacker exploited a public Marimo notebook via CVE-2026-39987, pulled two cloud credentials out of the host, replayed them through an 11-IP Cloudflare Workers egress pool, retrieved an SSH private key from AWS Secrets Manager, drove eight short SSH sessions against an internal bastion and exfiltrated the full schema and credential table of an internal PostgreSQL database. Total time from the WebSocket handshake to the database dump: under one hour. The hands-on-keyboard work between pivots was not done by a human and was not done by a precompiled script — Sysdig's behavioural reconstruction shows the post-compromise commands were generated and chained by an LLM agent reading tool output and deciding the next step on the fly.
This is not a research paper or a prompt-injection demo. It is a production breach with an attacker-side AI agent in the loop. Defenders who still calibrate their controls around "what a human red teamer would do in a day" need to recalibrate.
What CVE-2026-39987 actually is
Marimo is a reactive Python notebook that has picked up traction with data and ML teams. CVE-2026-39987 is a pre-auth RCE in the /terminal/ws endpoint: unlike the other WebSocket routes in the project, this one skipped validate_auth() entirely, checking only the run mode and platform support before handing out a PTY. CVSS 4.0 9.3 (CVSS 3.1 9.8), CWE-306 — missing authentication for a critical function. Fixed in 0.23.0; everything ≤0.20.4 is vulnerable. NVD published on 9 April 2026 and CISA added it to the KEV catalogue on 23 April 2026 with a 7 May federal due date — a 14-day clock that has now expired.
So the entry vector is the boring part. A reachable instance, an unauthenticated WebSocket, a full shell. What matters is what happened after.
The four pivots, in attacker time
Reconstructing from the Sysdig timeline:
| Phase | Time (UTC) | What happened |
|---|---|---|
| Initial access | 18:23:44 | WebSocket to vulnerable Marimo from 157.66.54.26 (AS141892, ID) |
| Credential harvest | 18:24:14 | AWS credentials pulled from environment files |
| AWS pivot | 19:26:31 | First AWS API call with harvested access key (48 min after harvest) |
| Secrets Manager | 19:26:52 | SSH private key retrieved via 12 redundant GetSecretValue requests in 22 seconds |
| Bastion + exfil | 19:30:30 – 19:32:23 | 8 parallel SSH sessions from 6 distinct Cloudflare Workers IPs, schema + credentials table dumped in 113 seconds |
Two specific things to stare at in that table. First, the gap between "credentials in hand" and "first AWS API call" is 48 minutes — likely the agent reasoning about the environment, choosing targets, deciding how to fan out. Second, the entire bastion-side exfiltration took 113 seconds across eight parallel sessions. The actual database extraction is over before any reasonable SIEM rule had aggregated and triaged the initial WebSocket alert.
The signature of an agent on the wire
The reason this matters more than yet-another-RCE-followed-by-data-theft is the behavioural signature Sysdig captured. Four structural fingerprints separate this from a pre-baked script:
- Improvised targeting. The PostgreSQL dump runs against a table the attacker could not have known about in advance. There is no pre-staging, no recon-then-execute split — the agent discovers, reasons, and dumps in one continuous sequence driven by tool output.
- Planning artefacts in the command stream. Across six distinct IPs in sub-second bursts, a Chinese-language comment ("see what else we can do") appears embedded in the command stream. A human running a playbook does not narrate to themselves across six parallel SSH sessions. An LLM stitching commands in real time does.
- Machine-optimised command syntax.
echo '---'separators between probes,2>&1 | head -Nbounded captures,-P pager=offon psql,2>/dev/nulleverywhere, quoted-EOF HEREDOCs bundling six SQL statements at once. This is the shape of commands produced by something that needs to read its own structured output back, not the shape of commands a human types into a shell. - Output-driven chaining. Each subsequent command consumes a value harvested from the previous command's stdout — not from a hard-coded playbook config. That is exactly the loop an agent runs: tool call → observe → decide → next tool call.
The 11-IP Cloudflare Workers fan-out is the other tell. A scripted operator who wanted egress diversity would have provisioned a fixed pool. An agent reasoning about rate-limiting and source-IP correlation will instinctively spread requests across whatever PoPs are available, in the pattern that minimises the per-IP signal. Sysdig saw 8 SSH sessions across 6 IPs and 12 Secrets Manager calls across the rest, all coordinated within seconds.
What's actually changing
The honest version of the cost story is in Sysdig's framing. A scripted operator amortises engineering time across many targets — the same playbook is replayed, with tweaks. An agent-driven operator amortises inference budget, which is cheaper and far more flexible. Adding a new target type no longer requires writing a new playbook; it requires letting the agent read the new environment and decide what to do.
A human red teamer needs 6-12 hours to chain a credential theft through AWS Secrets Manager into an SSH bastion and out via a PostgreSQL dump. The agent here did it in 60 minutes, with no per-target preparation, no fixed playbook to fingerprint, and an egress pattern that defeats single-IP rate limiting.
Two consequences fall out of this:
- The attacker can now target anything internet-reachable, not just things they have written tooling for. Long-tail software (Marimo, Langflow, ComfyUI, every newish ML/data tool with a web UI) becomes economically attractive overnight.
- Detection windows that were "minutes to hours" become "minutes to seconds." The end-to-end chain ran in under an hour. Any control that requires a human triage step in that window did not fire in time.
Why the usual stack does not catch this
Walk the controls:
- EDR/XDR on the host. The notebook process forks a shell. EDR sees process spawns and curl calls. None of them are individually malicious; the maliciousness is in the sequence. EDR rule sets do not reason across the 60-minute window or across the 11 egress IPs.
- Cloud audit logs. CloudTrail captured all 12
GetSecretValuecalls. The detection question is whether anyone aggregated and alerted on them within 22 seconds. In a typical SOC, "we found it in CloudTrail" is what people say at the post-mortem, not what fires the page. - Patch cadence. CISA added CVE-2026-39987 to KEV on 23 April with a 7 May federal due date. The victim here was compromised on 10 May — three days past the federal deadline. KEV is a floor, not a ceiling, and the floor was not met. This is the 21.3% known-CVE gap ENISA flagged in the 2025 Threat Landscape, made concrete.
- Annual or quarterly pentest. The next-scheduled pentest would have flagged Marimo as an exposed surface if it ran after 9 April. If it ran in March, it found nothing — the CVE did not exist yet. This is the basic problem with point-in-time validation that every regulator-aligned framework (NIS2, DORA) is now pushing to fix by mandating continuous evidence.
What actually works
Two layers, paired:
Continuous, AI-driven offensive validation. The defender needs an offensive engine that adapts to new CVEs in the window between disclosure and exploitation, that reasons about your environment the way an attacker's agent will, and that re-runs on every perimeter change. Quarterly pentests cannot model an attacker who needs no per-target preparation; you need a defender who needs no per-target preparation either.
Behavioural traffic analysis at line rate. The Sysdig writeup is, in effect, a worked example of what should have fired during the attack rather than after it. The signals were on the wire — anomalous WebSocket from a never-seen ASN, sustained outbound egress fan-out across 11 IPs in seconds, machine-paced Secrets Manager polling, parallel SSH sessions to a bastion that historically only sees one or two concurrent operators. Each one of those is detectable behaviourally before it completes. None of them require knowing the CVE in advance.
Where Zero Hunt fits
Two of Zero Hunt's three pillars speak directly to the Marimo intrusion.
Pillar 2 — AI Traffic Analysis is the load-bearing one for this scenario. The appliance runs a proprietary deep-learning model with four parallel inference heads (suspicious traffic, malware classification, attack-type identification, application fingerprinting) trained on billions of PCAP sequences, all at 2.7+ Gbit/s on local GPU. The 11-IP egress fan-out, the 22-second Secrets Manager polling burst, the eight-session SSH fan-in to a bastion that normally sees one session at a time — these are exactly the temporal-correlation anomalies the traffic model is built to fire on. No cloud round-trip, no nightly SIEM digest. Detection during the 113-second exfiltration window, not in next morning's incident review.
Pillar 1 — AI Generative Pentest answers the other half of the question. The 10-agent swarm (Recon, Exploit, Web, Credential, Post-Exploit, Pivot, Tactic, Report, plus the AI Controller) generates per-target exploit chains via a local LLM — not pulled from ExploitDB, not a fixed playbook. Backtested in the AI Gym (142+ self-evolving skills, validated against Vulhub and NYU CTF Bench) before any new technique touches a production environment. The point is symmetric: if an attacker can reason about your environment with an LLM agent and pivot in 60 minutes, your validation pipeline has to be able to do the same — continuously, signed at each step, against your actual perimeter.
The Marimo case is not a one-off. It is the first one Sysdig captured cleanly enough to publish. The next one will land against a different long-tail web UI, with a different CVE, against a different stack, and the only thing that will stay the same is the agent.