Skip to content

Security Independently confirmed3 publishers 2 min read Published Updated

A hand-debugged Python toolkit turned marimo CVE-2026-39987 into bastion SSH in eight seconds

Sysdig's threat research team watched one operator work a marimo notebook host for nine hours with hand-written scripts, and the eight-second jump to a bastion host at the end ran on tooling already staged on disk.

The Watch · Security desk

Send a correction

Illustration accompanying A hand-debugged Python toolkit turned marimo CVE-2026-39987 into bastion SSH in eight seconds
Generated illustration

What happened

  • Sysdig's threat research team watched one operator move from an open WebSocket to a live SSH session on a bastion host in eight seconds, with no agent in the loop and no LLM-generated scripts or tooling.
  • The flaw is CVE-2026-39987, a pre-authentication RCE in marimo: the /terminal/ws endpoint hands out an interactive PTY shell while skipping the authentication check the application's other WebSocket endpoints apply.
  • The chain ran in three steps: unauthenticated shell as the marimo process user, an AWS Secrets Manager call with credentials harvested from the instance, then SSH to a bastion host with the retrieved private key.
  • GitHub's advisory lists every marimo version up to and including 0.20.4 as affected, and 0.23.0 wires the missing validate_auth() call into the terminal endpoint via PR #9098.
  • The operator walked past a planted prompt injection that every agentic threat actor Sysdig has profiled against this same CVE tripped.

Why it matters

  • Who's exposed exposure Anyone running marimo next to an ML pipeline should treat the notebook host's instance role as the attacker's first credential and scope the blast radius to everything that role can read in Secrets Manager.
  • What it limits constraint Detection tuned to windows measured in minutes will only ever see this chain after it completes, so the alerting decision moves to the shell open and the script drops, not the credential pivot.
  • Who has to decide decision Exploit complexity offers no help in scheduling the upgrade here: an unauthenticated WebSocket needs no payload, so who can reach the port decides who is exposed.
  • What doesn't add up contradiction Sysdig calls the AI-lowers-the-bar question settled while presenting a human operator who outran and out-evaded the agents it profiled, and the post supplies no speed figures for those agents to compare against.

The eight seconds were a replay of work already finished. Sysdig's timeline puts the first interactive command, a TCP probe across the host's /24, and the first credentialed AWS API call nearly four hours apart, and Sysdig says that window is very likely when the operator built and debugged the tooling [9]. By the reconnection the scripts sat on disk, and the chain needed one command to fire [10]. Four hours of build against eight seconds of execution: preparation ran 1,800 times longer than the run [21].

Marimo notebooks tend to be deployed alongside ML pipelines, on hosts with GPU access, large datasets and credentialed connections to AWS, GCP and model providers, which is why Sysdig calls a compromised instance the door to the victim's cloud account [12].

Delivery was unremarkable. Each script arrived as `echo '<base64-blob>' | base64 -d > /tmp/<name>.py`, and eight unique ones went in over a 17-minute window [15]. That is one script about every two minutes [20]. Sysdig says the base64 wrap sidesteps shell-quoting problems with embedded multi-line Python [16]. The boto3 chain script had been written and debugged across multiple sessions before it was dropped, and Sysdig reports no evidence of AI use in that process [11].

Every earlier marimo intrusion Sysdig profiled looked different. Those operators typed AWS request-signing code out from memory, line by line, in a single shell session [17]. This operator ran more than 850 interactive commands across the nine-hour session and used no recognisable publicly available offensive tooling [8]. That works out at about 94 commands an hour, one every 38 seconds, sustained for nine hours on a notebook host [19]. The eight-second pivot gives a detection engine almost nothing to match on. The four hours that produced it were 850 commands of shell noise.

The post opens with a claim its case study does not test. "AI is lowering the barrier to entry for attackers; that much is settled," the Sysdig Threat Research Team wrote [13]. The evidence here is one operator in one vendor's telemetry, and the comparison set is Sysdig's own profiles of agentic actors against the same CVE, whose speeds the post does not quantify [14]. That series began with exploitation less than 10 hours after disclosure of CVE-2026-39987 and continued with the NKAbuse RAT campaign [18].

What to watch

  • A second victim showing the same echo-base64-into-/tmp/ delivery pattern, which would extend this from one session to a campaign.
  • Scan counts for internet-reachable marimo instances still serving /terminal/ws on 0.20.4 or earlier.
  • The same pre-staged toolkit appearing in another operator's hands, a sign it is being shared or sold.

Clarity's read

What the record supports and how the coverage leans. The claims behind it follow.

Reality

Evidence68
Adoption66
Hype gap+8
Incentives72
Confidence70

Perspective Coverage

3 publishers
Builder
Builder 33%
Operator
Operator 60%
Investor
Investor 7%
Why these scores

Claim ledger

Ranked by verification strength, evidence, and original report placement.

  1. [1]

    The Sysdig Threat Research Team watched a single threat actor go from an open WebSocket to a live SSH session on a bastion host in eight seconds, with no agent in the loop and no sign of LLM-generated scripts or tooling.

    Reported Supported Source: Sysdig Threat Research TeamView cited source
  2. [2]

    CVE-2026-39987 is a pre-authentication remote code execution flaw in marimo; the /terminal/ws WebSocket endpoint provides an interactive PTY shell but skips the authentication validation that other WebSocket endpoints in the same application apply correctly.

    Reported SupportedView cited source
  3. [3]

    Any client that can open a WebSocket to /terminal/ws is granted a full interactive shell running as the marimo process user with no credentials required, and exploitation requires no payload or encoding.

    Reported SupportedView cited source
  4. [4]

    The operator ran a complete credential-pivot chain end to end: initial access through the unauthenticated WebSocket terminal, an AWS Secrets Manager call using credentials harvested from the compromised instance, and SSH access to a bastion host with the retrieved private key.

    Reported SupportedView cited source
  5. [5]

    The operator used a Python toolkit they wrote and debugged by hand, in-session, over the preceding four hours.

    Reported SupportedView cited source
  6. [6]

    GitHub's advisory lists all versions up to and including marimo 0.20.4 as affected, with the fix shipped in 0.23.0, which wires the missing validate_auth() call into the terminal endpoint via PR #9098.

    Reported SupportedView cited source
  7. [7]

    The operator ignored a planted prompt injection that agent-driven operators reliably tripped, a trap every agentic threat actor Sysdig profiled against the same CVE fell into.

    Reported SupportedView cited source
  8. [8]

    Over the course of a nine-hour session the operator issued more than 850 interactive commands and used no recognizable publicly available offensive tooling.

    Reported SupportedView cited source
  9. [9]

    The first interactive command, a TCP probe across the host's /24, and the first credentialed AWS API call sit nearly four hours apart; Sysdig says that window is very likely when the operator built and debugged their tooling.

    Reported SupportedView cited source
  10. [10]

    Once the toolkit was complete and working, subsequent reconnections completed the full chain in seconds because the scripts were already on disk and only needed a single command to fire; the toolkit was pre-staged during an earlier session.

    Reported SupportedView cited source
  11. [11]

    The operator wrote and debugged a boto3 chain script over multiple sessions and dropped it as a base64-encoded Python file into /tmp/; there was no evidence suggesting the threat actor used AI during this process.

    Reported SupportedView cited source
  12. [12]

    Marimo notebooks are commonly deployed alongside ML pipelines on hosts with GPU access, large datasets and credentialed connections to AWS, GCP and various model providers, and Sysdig says a compromised marimo instance is the door to the victim's cloud account.

    Reported SupportedView cited source
  13. [13]

    "AI is lowering the barrier to entry for attackers; that much is settled."

    Reported Supported Source: Sysdig Threat Research Team blog postView cited source
  14. [14]

    This is one of several operators Sysdig has profiled against CVE-2026-39987; Sysdig concludes that skilled human attackers can move at machine speed and can often better evade defenders' detections.

    Reported SupportedView cited source
  15. [15]

    The attacker iterated through eight unique scripts over a 17-minute window, each base64-decoded into /tmp/ via the pattern echo '<base64-blob>' | base64 -d > /tmp/<name>.py.

    Reported SupportedView cited source
  16. [16]

    The base64 wrap sidesteps shell-quoting issues with embedded multi-line Python.

    Reported SupportedView cited source
  17. [17]

    Every attack on marimo before this one showed fingerprints of LLM-driven operators, who typed out AWS request-signing code from memory, line by line, in a single shell session.

    Reported SupportedView cited source
  18. [18]

    Sysdig's series on CVE-2026-39987 began with exploitation less than 10 hours after disclosure and continued with the NKAbuse RAT campaign.

    Reported SupportedView cited source
  19. [19]

    More than 850 interactive commands across a nine-hour session is about 94 commands an hour, or one every 38 seconds.

    Derived Supported
  20. [20]

    Eight scripts dropped over a 17-minute window is one script about every two minutes.

    Derived Supported
  21. [21]

    The four-hour build-and-debug period was 1,800 times as long as the eight-second execution of the chain.

    Derived Supported

Sources

3 independent publishers whose own reporting we read for this story.

  1. infosecurity-magazine.com

    1 article · September 14, 2026

    Human Attacker Hits Machine-Speed Exploitation of Marimo RCE
  2. thehackernews.com

    1 article · September 15, 2026

    Human Attacker Exploits Marimo RCE, Reaches SSH Bastion in Eight Seconds
  3. webflow.sysdig.com

    1 article · September 10, 2026

    Machine speed, hold the AI: Hand-rolled marimo CVE-2026-39987 exploit

Topics and entities