The security industry has spent the last two years warning that AI-assisted exploitation is compressing the time between vulnerability disclosure and weaponization. Sysdig's latest threat research delivers a sobering counterpoint: you don't need AI to move fast. A skilled human operator, working manually, pivoted from an exploited Marimo notebook to an internal SSH bastion host in eight seconds.
That number should recalibrate every incident response plan your organization has. The traditional assumption — that you have minutes or hours between initial access and lateral movement — is dead. In this intrusion, the attacker's hands were already on the keyboard, the target environment was already mapped, and the exploitation chain was rehearsed. By the time most EDR pipelines would have finished enriching the first alert, the adversary was already inside a second system.
Marimo is an open-source reactive Python notebook — a modern alternative to Jupyter that has gained significant adoption in data science and ML engineering teams. Like Jupyter before it, Marimo notebooks are frequently deployed in cloud environments, often exposed to the internet for collaboration convenience, and routinely run with far more privilege than their use case justifies. A critical remote code execution flaw in Marimo turns that convenience into an initial access vector with direct execution capability — no payload staging, no phishing, no malware. The notebook is the execution environment.
If your organization runs Marimo, Jupyter, or any notebook interface reachable from outside your hardened perimeter, treat this as an active-threat briefing, not a thought piece.
Technical Analysis
The Attack Chain
Based on Sysdig's reporting, the intrusion followed a pattern we have seen repeatedly in cloud IR engagements, but executed with unusual speed:
-
Initial Access — Marimo RCE. The attacker identified an internet-accessible Marimo notebook instance and exploited a critical code execution vulnerability. Notebook servers are uniquely dangerous initial access points: by design, they execute arbitrary user-supplied Python code. An RCE in the application layer means the attacker inherits whatever identity, network position, and cloud credentials the notebook process holds — typically a service account with access to data stores, internal APIs, and cloud instance metadata.
-
Immediate Environment Reconnaissance. Within seconds of code execution, the operator enumerated network configuration, running services, and — critically — SSH material. Notebook pods and VMs in data science environments frequently contain SSH private keys (for Git access, cluster hopping, or data transfer), cloud credentials in environment variables, and kubeconfig files.
-
Lateral Movement to the SSH Bastion — T+8 seconds. Using credentials or network access obtained from the compromised notebook, the attacker pivoted directly to an SSH bastion host. Bastions are force multipliers for attackers: they are trusted jump points into restricted network segments, they often hold broad connectivity to production assets, and their authentication logs are where defenders expect to see legitimate admin traffic — providing excellent cover.
Why Notebooks Keep Failing in Production
In fifteen years of IR work, notebook servers are one of the most reliably compromised asset classes in cloud environments. The reasons are structural:
- Execution by design. There is no meaningful line between "using the product" and "executing arbitrary code." Traditional application-layer exploit detection has almost nothing to key on.
- Over-privileged identities. Data scientists need data access. In practice, that means notebook service accounts accumulate broad read access to storage buckets, databases, and secrets managers.
- Internet exposure for convenience. Notebooks get stood up quickly for demos, workshops, and ad-hoc analysis — and rarely come down. Sysdig and other cloud security vendors have consistently found exposed notebook instances indexed on Shodan and Censys.
- Weak or absent authentication. Default configurations of many notebook servers, especially when fronted by no reverse proxy, provide unauthenticated or token-only access. A leaked or brute-forced token is full RCE.
Exploitation Status
This is confirmed in-the-wild exploitation observed by Sysdig's threat research team against a real customer environment — not a theoretical proof of concept. The Marimo maintainers have addressed the code execution flaw; organizations running internet-reachable Marimo instances should assume they are being scanned for and targeted. The speed of the observed pivot indicates an operator with prior reconnaissance of the target environment, consistent with the broader trend of attackers pre-staging target lists of exposed development and analytics infrastructure.
Detection & Response
The eight-second pivot window means detection must be oriented around automated response on the first observable, not alert queues. The most reliable detection surface is not the Marimo exploit itself (which looks like normal notebook usage) — it is what the notebook process does immediately afterward: spawning shells, reading SSH keys, enumerating the network, and initiating outbound SSH connections.
Sigma Rules
The following rules target Linux process creation telemetry (Sysmon for Linux, auditd, or EDR). They focus on the highest-fidelity behavioral indicator in this intrusion: a Python/notebook process spawning interactive shells, credential access tools, or SSH clients.
---
title: Notebook Server Process Spawning Shell or System Utility
id: 3f8a2c71-9b4e-4d12-a6c8-5e1f7b9d2043
status: experimental
description: Detects a Python/notebook server process (marimo, jupyter, ipython) spawning shells or reconnaissance utilities, consistent with post-exploitation of a notebook RCE as reported by Sysdig.
references:
- https://thehackernews.com/2026/09/human-attacker-exploits-marimo-rce.html
- https://attack.mitre.org/techniques/T1059/006/
author: Security Arsenal
date: 2026/09/15
tags:
- attack.execution
- attack.t1059.006
- attack.t1190
logsource:
category: process_creation
product: linux
detection:
selection_parent:
ParentCommandLine|contains:
- 'marimo'
- 'jupyter'
- 'ipython'
- 'notebook'
selection_child:
Image|endswith:
- '/bash'
- '/sh'
- '/zsh'
- '/dash'
- '/curl'
- '/wget'
- '/nc'
- '/ncat'
- '/nmap'
condition: selection_parent and selection_child
falsepositives:
- Data science workflows using os.system or subprocess for legitimate package installs
- Notebook extensions invoking shell commands
level: high
---
title: Notebook Process Reading SSH Key Material
id: 8c1d4e52-7a3b-4f96-b2d1-9e6c3a5f8127
status: experimental
description: Detects notebook server processes accessing SSH private keys or authorized_keys files, a key credential theft behavior observed in the Marimo intrusion chain.
references:
- https://thehackernews.com/2026/09/human-attacker-exploits-marimo-rce.html
- https://attack.mitre.org/techniques/T1552/004/
author: Security Arsenal
date: 2026/09/15
tags:
- attack.credential_access
- attack.t1552.004
logsource:
category: file_event
product: linux
detection:
selection_path:
TargetFilename|contains:
- '/.ssh/id_rsa'
- '/.ssh/id_ed25519'
- '/.ssh/id_ecdsa'
- '/.ssh/authorized_keys'
- '/.ssh/config'
selection_proc:
Image|endswith:
- '/python'
- '/python3'
filter_legit:
CommandLine|contains:
- 'pip install'
- 'git'
condition: selection_path and selection_proc and not filter_legit
falsepositives:
- Legitimate Git-over-SSH operations from notebooks (clone/pull)
level: high
---
title: Outbound SSH Connection From Notebook or Python Process
id: 5b2e9f14-6c8d-4a73-c1e5-8f4b2d7a9063
status: experimental
description: Detects SSH client execution parented to a Python/notebook process, consistent with the rapid lateral movement from Marimo to an SSH bastion observed by Sysdig.
references:
- https://thehackernews.com/2026/09/human-attacker-exploits-marimo-rce.html
- https://attack.mitre.org/techniques/T1021/004/
author: Security Arsenal
date: 2026/09/15
tags:
- attack.lateral_movement
- attack.t1021.004
logsource:
category: process_creation
product: linux
detection:
selection:
Image|endswith:
- '/ssh'
- '/scp'
- '/sftp'
ParentCommandLine|contains:
- 'python'
- 'marimo'
- 'jupyter'
condition: selection
falsepositives:
- Notebooks with documented Git-over-SSH or paramiko-based automation workflows
level: critical
Tuning guidance: The third rule is your crown jewel. Outbound SSH initiated by a notebook process is almost never legitimate in production data science environments — Git operations typically flow through the git binary, not raw ssh invocations from a Python parent. Baselining your environment for one week will tell you quickly whether you have exceptions. If you do, scope them by destination host in an allowlist rather than disabling the rule.
KQL — Microsoft Sentinel / Defender
Notebook workloads increasingly run in Azure ML, AKS, or on Linux VMs ingested into Sentinel via Syslog/CEF. This query hunts the same behavior chain: shell or SSH execution descending from notebook processes, plus follow-on network connections to port 22 from unexpected sources.
// Hunt: Notebook process spawning shells, recon tools, or SSH clients
// Sources: Defender for Endpoint (DeviceProcessEvents) or Syslog-ingested Linux telemetry
let NotebookProcs = dynamic(["marimo", "jupyter", "jupyter-lab", "jupyter-notebook", "ipython"]);
let SuspiciousChildren = dynamic(["bash", "sh", "zsh", "dash", "ssh", "scp", "sftp", "curl", "wget", "nc", "ncat", "nmap", "masscan"]);
DeviceProcessEvents
| where TimeGenerated > ago(7d)
| where InitiatingProcessCommandLine has_any (NotebookProcs)
or ProcessCommandLine has_any (NotebookProcs)
| extend ChildProc = tolower(FileName)
| where ChildProc in~ (SuspiciousChildren)
| project TimeGenerated, DeviceName, AccountName,
ParentProcess = InitiatingProcessCommandLine,
ChildProcess = ProcessCommandLine,
RemoteIP = InitiatingProcessRemoteIP, SHA256
| order by TimeGenerated asc;
// Correlate: outbound SSH from hosts running notebook services
let NotebookHosts =
DeviceProcessEvents
| where TimeGenerated > ago(7d)
| where ProcessCommandLine has_any ("marimo", "jupyter", "ipython")
| summarize by DeviceName;
DeviceNetworkEvents
| where TimeGenerated > ago(7d)
| where DeviceName in (NotebookHosts)
| where RemotePort == 22 and ActionType == "ConnectionSuccess"
| where InitiatingProcessFileName !in~ ("sshd", "git", "ssh-agent")
| summarize Connections = count(),
FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated),
Targets = make_set(RemoteIP, 20)
by DeviceName, InitiatingProcessFileName, InitiatingProcessAccountName
| order by FirstSeen asc;
For pure Syslog ingestion (no Defender for Endpoint), pivot on Syslog where ProcessName matches sshd and look for accepted publickey/password authentications originating from your notebook subnets — bastion logons sourced from data science VLANs are anomalous by definition in most environments.
Velociraptor VQL
For rapid scoping of a suspected compromised notebook host, this artifact identifies notebook processes alongside their network connections and checks for recently accessed SSH key material.
-- Hunt: Notebook RCE post-exploitation triage
-- Identifies notebook processes, their SSH/network connections, and suspicious child processes
LET notebook_procs = SELECT Pid, Ppid, Name, CommandLine, Exe, Username, CreateTime
FROM pslist()
WHERE CommandLine =~ '(?i)(marimo|jupyter|ipython)'
LET suspicious_children = SELECT Pid, Ppid, Name, CommandLine, Username, CreateTime
FROM pslist()
WHERE Name =~ '(?i)^(ssh|scp|sftp|bash|sh|curl|wget|nc|ncat)$'
AND Ppid IN (SELECT Pid FROM pslist() WHERE CommandLine =~ '(?i)(marimo|jupyter|ipython|python)')
LET ssh_connections = SELECT Pid, Name, LocalAddr, LocalPort, RemoteAddr, RemotePort, Status
FROM netstat()
WHERE RemotePort = 22 AND Status = 'ESTABLISHED'
SELECT 'notebook_process' AS Artifact, Pid, Ppid, Name, CommandLine, Username,
CreateTime, '' AS RemoteAddr, '' AS RemotePort
FROM notebook_procs
UNION ALL
SELECT 'suspicious_child' AS Artifact, Pid, Ppid, Name, CommandLine, Username,
CreateTime, '' AS RemoteAddr, '' AS RemotePort
FROM suspicious_children
UNION ALL
SELECT 'ssh_connection' AS Artifact, Pid, 0 AS Ppid, Name, '' AS CommandLine,
'' AS Username, '' AS CreateTime,
format("%v:%v", args=[RemoteAddr, RemotePort]) AS RemoteAddr,
str(RemotePort) AS RemotePort
FROM ssh_connections
Follow up on any hit by collecting /home/*/.ssh/, shell histories, and the Marimo server logs — and treat any SSH private key present on the host as compromised pending rotation.
Remediation & Hardening Script
This Bash script audits a Linux host (or container image build pipeline) for Marimo exposure, verifies the installed version, checks for listening interfaces, and applies baseline hardening. Adapt the version check to the fixed release per the Marimo security advisory in your environment.
#!/bin/bash
# Marimo RCE exposure audit and hardening — Security Arsenal
# Run on notebook hosts, container entrypoints, or bake into CI image scanning.
set -euo pipefail
echo "=== [1] Installed Marimo version ==="
if command -v marimo &>/dev/null; then
MARIMO_VER=$(marimo --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
echo "Installed: ${MARIMO_VER}"
pip install --upgrade marimo
echo "Upgraded to: $(marimo --version 2>/dev/null | head -1)"
else
echo "marimo binary not found on PATH — checking pip..."
pip show marimo 2>/dev/null | grep -E '^(Name|Version)' || echo "Marimo not installed via pip."
fi
echo "=== [2] Listening interfaces (0.0.0.0 = internet/LAN exposed) ==="
ss -tlnp 2>/dev/null | grep -E 'python|marimo|jupyter' || echo "No notebook listeners detected."
EXPOSED=$(ss -tln 2>/dev/null | grep -E '0\.0\.0\.0:(2718|8888|8080)' || true)
if [ -n "$EXPOSED" ]; then
echo "WARNING: Notebook bound to all interfaces:"
echo "$EXPOSED"
fi
echo "=== [3] Marimo processes running with edit/execution enabled ==="
ps aux | grep -E 'marimo.*(run|edit)' | grep -v grep || echo "No active marimo edit sessions."
echo "=== [4] SSH private keys present on host (credential exposure risk) ==="
find /home /root -maxdepth 3 -name 'id_*' ! -name '*.pub' -perm -400 2>/dev/null || true
echo "=== [5] Cloud metadata reachability from this host ==="
if timeout 2 curl -s -H 'Metadata-Flavor: Google' http://169.254.169.254/ &>/dev/null \
|| timeout 2 curl -s -H 'Metadata: true' 'http://169.254.169.254/metadata/instance?api-version=2021-02-01' &>/dev/null; then
echo "WARNING: Instance metadata service reachable. Enforce IMDSv2/hop-limit=1 or block from notebook workloads."
fi
echo "=== [6] Baseline hardening: restrict notebook to localhost + reverse proxy ==="
# Recommended launch posture for marimo:
# marimo run --host 127.0.0.1 --port 2718 (never --host 0.0.0.0 without an authenticating proxy)
# Add egress filtering so notebook hosts cannot initiate outbound TCP/22:
if command -v iptables &>/dev/null; then
iptables -C OUTPUT -p tcp --dport 22 -m owner ! --uid-owner root -j REJECT 2>/dev/null || \
iptables -A OUTPUT -p tcp --dport 22 -m owner ! --uid-owner root -j REJECT
echo "Egress rule added: non-root outbound SSH denied (adjust for your admin UID model)."
fi
echo "=== Audit complete. Review warnings above and rotate any discovered credentials. ==="
Remediation
Given confirmed in-the-wild exploitation, sequence your response as follows:
-
Patch immediately. Upgrade Marimo to the latest released version across all environments — including container base images, which is where stale notebook versions hide longest. Pin and rebuild; do not rely on runtime
pip install --upgradein long-lived containers. Consult the official Marimo GitHub repository and its security advisories for the fixed version applicable to your deployment. -
Inventory exposure now. Query Shodan/Censys and your own external attack surface management tooling for Marimo's default port (2718) and Jupyter's (8888) across your IP space. Anything internet-reachable should be treated as potentially compromised, not merely vulnerable.
-
Assume breach on exposed instances. If you find an internet-facing Marimo instance, initiate IR scoping: review process execution, outbound connections (especially TCP/22), cloud audit logs (CloudTrail/Activity Log/Audit Logs) for the attached identity, and rotate every credential the notebook host could touch — SSH keys, cloud IAM credentials, kubeconfigs, database passwords, and API tokens in environment variables.
-
Eliminate direct internet exposure. Bind notebook servers to localhost and place them behind an authenticating reverse proxy (SSO/OIDC via oauth2-proxy, Pomerium, or your IdP-aware load balancer). For interactive development, prefer brokered access (e.g., through your VDI, bastion with MFA, or cloud-native solutions like AWS SageMaker/Vertex AI with IAM enforcement).
-
Break the pivot path. The eight-second pivot succeeded because the notebook could reach the bastion. Enforce network segmentation so notebook workloads cannot initiate SSH to infrastructure subnets. Apply egress filtering, and scope cloud instance metadata access (IMDSv2 with hop limit 1, or block entirely from notebook pods).
-
Reduce credential blast radius. Never store long-lived SSH private keys on notebook hosts. Use short-lived certificates (SSH CAs such as Smallstep or your cloud's native mechanisms — EC2 Instance Connect, Azure AD SSH, OS Login) so stolen key material has minimal value.
-
Automate the first response. With an eight-second pivot window, human triage is too slow. Wire your highest-fidelity detections (notebook → SSH client execution) to automated containment: isolate the host, revoke the attached cloud session credentials, and alert. Playbook it, test it, measure it.
The Broader Lesson
The Sysdig finding is a useful corrective to the AI-hype cycle. Speed in post-exploitation has never required artificial intelligence — it requires preparation, and mature adversaries have always had it. What has changed is the population of operators capable of this tempo. Defenders should respond not with new dashboards but with pre-approved, automated containment on high-fidelity behavioral signals. If a notebook process spawns an SSH client, that host should be isolated before a human ever sees the alert. In 2026, that is the only response model that matches the observed adversary clock speed.
Related Resources
Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub
Is your security operations ready?
Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.