Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-39987 — Detection and exploitation toolkit for CVE-2026-39987, a pre-auth RCE in Marimo notebooks. Includes Python scanner and Nmap NSE script to identify vulnerable instances via WebSocket endpoint checks. | Kitploit
Tools/GitHubGitHub/keraattin/cve-2026-39987
Vulnerability ScannersVulnerability AnalysisExploitationWeb Application ExploitationInformation GatheringWeb SecurityNetwork SecurityPenetration Testing
GitHubkeraattin/cve-2026-39987

CVE-2026-39987

Detection and exploitation toolkit for CVE-2026-39987, a pre-auth RCE in Marimo notebooks. Includes Python scanner and Nmap NSE script to identify vulnerable instances via WebSocket endpoint checks.

125 months agoNot yet reviewed
View Repository

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-39987 — Marimo Python Notebook Pre-Authenticated Remote Code Execution

CVE-2026-39987 CVSS 9.3 CWE-306 Marimo Pre-Auth RCE

TL;DR

A pre-authenticated remote code execution vulnerability in Marimo, an open-source Python notebook for data science and AI/ML. The terminal WebSocket endpoint (/terminal/ws) completely skips authentication validation, while the neighboring notebook endpoint (/ws) correctly enforces it. An unauthenticated attacker can connect to /terminal/ws and obtain a full interactive PTY shell on the host system with zero credentials.

Exploited in the wild within 10 hours of disclosure. Attackers stole AWS credentials in under 3 minutes.

Affects Marimo <= 0.20.4. Fixed in Marimo 0.23.0.


Table of Contents

  • Quick Facts
  • What is Marimo?
  • Vulnerability Deep Dive
    • The Two WebSocket Endpoints
    • The Missing Auth Check
    • The Attack: Advisory to AWS Keys in 3 Minutes
  • Impact Analysis
  • Affected Versions
  • The Bigger Picture: AI/ML Toolchain Under Attack
  • Detection
    • Python Scanner
    • Nmap NSE Script
    • Manual Verification
  • Indicators of Compromise
  • Remediation
  • References
  • Author

Quick Facts

FieldDetail
CVE IDCVE-2026-39987
VendorMarimo Project
ProductMarimo (Python Notebook)
Affected Versions<= 0.20.4
CVSS v3.19.3 (Critical)
CWECWE-306 — Missing Authentication for Critical Function
Attack VectorNetwork
AuthenticationNone required
User InteractionNone
Exploit MaturityActively exploited in the wild
Time to Exploitation~10 hours after disclosure
Patched InMarimo 0.23.0

What is Marimo?

Marimo is an open-source reactive Python notebook designed as a modern alternative to Jupyter. It's built for data science, AI/ML experimentation, and interactive data analysis. Its key features include automatic dependency tracking, reproducible execution, and a cleaner developer experience compared to traditional notebooks.

Marimo is gaining rapid traction in the Python and AI/ML community, especially among practitioners who want more structured notebook workflows than Jupyter provides.

Like all notebook environments, Marimo instances typically have access to sensitive resources: cloud credentials (AWS, GCP, Azure), database connection strings, API keys for AI services (OpenAI, Anthropic, etc.), and internal network access. Unlike traditional web applications, notebooks are designed to execute arbitrary code. That's their core purpose.

This combination makes any authentication bypass in a notebook environment particularly devastating.

root@kitploit:~
  Typical Marimo Deployment:

  ┌──────────────┐         ┌────────────────────────────────┐
  │              │  HTTP   │          Marimo Server         │
  │   Browser    │────────>│                                │
  │   (User)     │         │  ┌──────────────────────────┐  │
  │              │<────────│  │  /ws (Notebook)          │  │
  └──────────────┘  WS     │  │  ✅ validate_auth()     │  │
                           │  └──────────────────────────┘  │
                           │                                │
                           │  ┌──────────────────────────┐  │
                           │  │  /terminal/ws            │  │
                           │  │  ❌ NO AUTH CHECK        │  │
                           │  └──────────────────────────┘  │
                           │                                │
                           │  ┌──────────────────────────┐  │
                           │  │  Python Environment      │  │
                           │  │  .env files              │  │
                           │  │  AWS credentials         │  │
                           │  │  API keys                │  │
                           │  └──────────────────────────┘  │
                           └────────────────────────────────┘

Vulnerability Deep Dive

The Two WebSocket Endpoints

Marimo's server implements multiple WebSocket endpoints for different features. The critical difference between the two main endpoints is the presence (or absence) of an authentication check:

root@kitploit:~
  Authentication Flow Comparison:

  /ws (Notebook WebSocket):
  ┌─────────┐    ┌───────────────┐    ┌──────────┐    ┌───────────┐
  │ Connect │───>│ validate_auth │───>│  Accept  │───>│ Notebook  │
  └─────────┘    └───────┬───────┘    └──────────┘    └───────────┘
                         │
                    ❌ Reject if
                    not authenticated

  /terminal/ws (Terminal WebSocket):
  ┌─────────┐    ┌───────────────┐    ┌──────────┐    ┌───────────┐
  │ Connect │───>│ Check mode &  │───>│  Accept  │───>│ PTY Shell │
  └─────────┘    │ platform only │    └──────────┘    └───────────┘
                 └───────────────┘
                 ⚠️ No auth check!
                 Anyone gets a shell!

The Missing Auth Check

The notebook endpoint (/ws) correctly calls validate_auth() to verify the user's identity before accepting WebSocket connections. This is the expected security behavior.

The terminal endpoint (/terminal/ws) only checks whether the server is in running mode and whether the platform supports terminal functionality. It never calls validate_auth(). After passing these basic checks, it accepts the connection and creates a full PTY (pseudo-terminal) session.

root@kitploit:~
# /ws (Notebook) — CORRECT implementation
async def websocket_connect(self, message):
    await self.validate_auth()      # ✅ Checks authentication
    await self.accept()
    # ... notebook communication

# /terminal/ws (Terminal) — VULNERABLE implementation
async def websocket_connect(self, message):
    if not self.is_running_mode():  # Only checks mode
        await self.close()
        return
    if not self.is_platform_supported():  # Only checks platform
        await self.close()
        return
    await self.accept()             # ❌ No auth! Anyone gets a shell
    # ... PTY shell creation

This is CWE-306: Missing Authentication for Critical Function. The most dangerous endpoint on the server (the one that provides an interactive shell) has no authentication whatsoever.

The Attack: Advisory to AWS Keys in 3 Minutes

The exploitation timeline shows how fast modern threat actors operate:

root@kitploit:~
  ┌──────────────────────────────────────────────────────────────┐
  │                   CVE-2026-39987 Timeline                    │
  ├──────────────────────────────────────────────────────────────┤
  │                                                              │
  │  T+0h        Advisory published                              │
  │  ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─                       │
  │  T+9h        First exploit built from advisory               │
  │  T+10h       Exploitation in the wild confirmed              │
  │  ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─                       │
  │  T+10h 0m    Attacker connects to /terminal/ws               │
  │  T+10h 1m    Full PTY shell obtained                         │
  │  T+10h 2m    .env file located and read                      │
  │  T+10h 3m    AWS keys exfiltrated                            │
  │              Total attack time: ~3 minutes                   │
  └──────────────────────────────────────────────────────────────┘

The attack itself is trivially simple:

root@kitploit:~
  Step 1: Attacker opens WebSocket connection to /terminal/ws
          (No authentication needed, no special tools required)

  Step 2: Server creates a PTY (pseudo-terminal) session
          Attacker now has an interactive shell

  Step 3: Attacker runs commands:
          $ cat .env
          AWS_ACCESS_KEY_ID=AKIA...
          AWS_SECRET_ACCESS_KEY=...
          DATABASE_URL=postgres://...
          OPENAI_API_KEY=sk-...

  Step 4: Credentials exfiltrated
          Attacker now has cloud access, database access,
          and API keys for AI services

  Total time: under 3 minutes
  Authentication required: none
  Tools required: any WebSocket client

No exploit development needed. No shellcode. No memory corruption. Just a WebSocket client and a missing auth check.


Impact Analysis

Immediate impact on the Marimo host:

  • Full interactive shell with the privileges of the Marimo process
  • Access to all files readable by the process (source code, data, credentials)
  • Access to environment variables containing API keys and secrets
  • Ability to execute arbitrary commands on the host system

Credential exposure (the primary attack goal):

  • AWS access keys and secret keys from .env files or environment variables
  • GCP/Azure service account credentials
  • Database connection strings with passwords
  • OpenAI, Anthropic, and other AI service API keys
  • SSH keys and other authentication material

Downstream impact (via stolen credentials):

  • Unauthorized access to cloud infrastructure (EC2, S3, Lambda, etc.)
  • Data exfiltration from cloud storage and databases
  • Resource abuse (cryptomining, AI API credit theft)
  • Lateral movement into cloud and on-premise networks

Risk amplification factors:

  • Notebook environments are designed to execute arbitrary code (that's their purpose)
  • Data science environments typically have broad cloud access for training jobs
  • Many Marimo instances are exposed to the internet for collaboration and remote work
  • Security hardening is often an afterthought in research/experimentation environments

Affected Versions

VersionStatus
Marimo 0.23.0+Patched
Marimo 0.20.5 to 0.22.xLikely vulnerable (between advisory range and fix)
Marimo <= 0.20.4Vulnerable (confirmed range)

The Bigger Picture: AI/ML Toolchain Under Attack

CVE-2026-39987 is not an isolated incident. It's part of a clear pattern that emerged in April 2026:

CVEProductTypeStatus
CVE-2026-39987MarimoPre-Auth RCE (WebSocket)Exploited in 10 hours
CVE-2026-33017LangflowRCECISA KEV (March 26)
CVE-2026-5059aws-mcp-serverCommand Injection RCEPublic advisory
TorchGeoTorchGeoeval() RCEPublic advisory

Four AI/ML development tools hit with critical RCE vulnerabilities in a single month. The AI/ML development pipeline is becoming the new shadow IT: tools deployed with broad access, minimal security oversight, and rich credential stores.

root@kitploit:~
  ┌─────────────────────────────────────────────────┐
  │        Why AI/ML Tools Are Prime Targets        │
  ├─────────────────────────────────────────────────┤
  │                                                 │
  │  1. DESIGNED to execute arbitrary code          │
  │     (that's literally what notebooks do)        │
  │                                                 │
  │  2. Run with elevated privileges                │
  │     (GPU access, cloud SDKs, network access)    │
  │                                                 │
  │  3. Contain high-value credentials              │
  │     (AWS keys, API tokens, DB connections)      │
  │                                                 │
  │  4. Often exposed to the network                │
  │     (for collaboration and remote access)       │
  │                                                 │
  │  5. Security hardening is an afterthought       │
  │     (focus on features and UX, not security)    │
  │                                                 │
  │  6. Users are researchers, not security experts │
  │     (default configs, weak passwords, no VPN)   │
  └─────────────────────────────────────────────────┘

Detection

Python Scanner

The Python script detects vulnerable Marimo instances through a multi-step analysis.

How it works:

  1. Marimo Identification — Queries /api/status, /api/health, and / for Marimo indicators in response content and headers
  2. Version Extraction — Parses version information from API responses, server headers, and HTML content
  3. WebSocket Handshake Test — Sends a safe HTTP Upgrade request to /terminal/ws (no data transmitted through the connection)
  4. Differential Auth Check — Compares behavior of /terminal/ws (should require auth) vs /ws (known to require auth) to confirm the inconsistency
  5. Version Vulnerability Check — Compares detected version against the vulnerable range (<= 0.20.4) and patched version (>= 0.23.0)

No commands are executed on target systems. The WebSocket handshake is tested but no data is sent through the connection. The check is entirely passive and safe for production.

Usage:

root@kitploit:~
# Install dependencies
pip install -r requirements.txt

# Single target (Marimo default port: 2718)
python CVE-2026-39987_Marimo_RCE_detector.py -t http://marimo-host:2718

# HTTPS target
python CVE-2026-39987_Marimo_RCE_detector.py -t https://marimo-host:443

# Bulk scan from file with verbose output
python CVE-2026-39987_Marimo_RCE_detector.py -f targets.txt -o results.json -v

# Increased timeout for slow networks
python CVE-2026-39987_Marimo_RCE_detector.py -t http://10.0.0.5:2718 --timeout 15

Options:

FlagDescriptionDefault
-t, --targetSingle target URL (e.g., http://host:2718)—
-f, --fileFile with target URLs, one per line (# comments supported)—
-o, --outputSave results to JSON file—
--timeoutConnection timeout in seconds10
--verify-sslEnable SSL certificate verificationDisabled
-v, --verboseVerbose output with full detailsOff

Example output:

root@kitploit:~
[*] CVE-2026-39987 Marimo Pre-Auth RCE Scanner
[*] Scanning 1 target(s)...
[*] NOTE: This scanner only checks for endpoint exposure.
[*]       No commands are executed on target systems.

======================================================================
Target: http://10.0.0.5:2718
Scan Time: 2026-04-14T16:00:00Z
Risk Level: CRITICAL
======================================================================
  Is Marimo:             YES
  Marimo Version:        0.19.2
  /terminal/ws Open:     YES — UNAUTHENTICATED
  Vulnerable:            YES

  *** CRITICAL: Pre-authenticated RCE is possible! ***
  *** An attacker can get a full PTY shell without any auth ***

  Details:
    - Marimo instance detected via /api/status
    - Marimo version: 0.19.2
    - WebSocket upgrade accepted — /terminal/ws accessible WITHOUT auth
    - CONFIRMED: /terminal/ws accepts unauthenticated connections while
      /ws requires auth — classic CVE-2026-39987 signature
    - Version 0.19.2 <= 0.20.4 — VULNERABLE to pre-auth RCE

======================================================================
[*] Scan Complete: 1 targets scanned
[*] Marimo Instances: 1 | Vulnerable: 1 | Critical: 1
======================================================================

Nmap NSE Script

root@kitploit:~
# Install the NSE script
sudo cp CVE-2026-39987_Marimo_RCE.nse /usr/share/nmap/scripts/
sudo nmap --script-updatedb

# Basic scan (Marimo default port: 2718)
nmap -p 2718 --script CVE-2026-39987_Marimo_RCE <target>

# Scan common ports where Marimo might run
nmap -p 2718,8080,8443,443 --script CVE-2026-39987_Marimo_RCE <target>

# Subnet scan
nmap -p 2718 --script CVE-2026-39987_Marimo_RCE 10.0.0.0/24

# Scan targets from a file
nmap -p 2718 --script CVE-2026-39987_Marimo_RCE -iL targets.txt

# With service version detection
nmap -sV -p 2718 --script CVE-2026-39987_Marimo_RCE <target>

Example Nmap output:

root@kitploit:~
PORT     STATE SERVICE
2718/tcp open  http
| CVE-2026-39987_Marimo_RCE:
|   VULNERABLE:
|   Marimo Pre-Auth RCE (CVE-2026-39987)
|     State: VULNERABLE
|     Risk level: CRITICAL
|     Marimo Version: 0.19.2
|     /terminal/ws: accessible without authentication
|     Description:
|       The Marimo /terminal/ws WebSocket endpoint accepts connections
|       without authentication, enabling pre-authenticated RCE.
|       An attacker can obtain a full PTY shell without any credentials.
|     References:
|_      https://nvd.nist.gov/vuln/detail/CVE-2026-39987

Manual Verification

If you have access to the Marimo instance:

root@kitploit:~
# Check Marimo version via API
curl -s http://<TARGET>:2718/api/status | python3 -m json.tool

# Test WebSocket upgrade on /terminal/ws (should NOT succeed without auth)
curl -s -o /dev/null -w "%{http_code}" \
  -H "Upgrade: websocket" \
  -H "Connection: Upgrade" \
  -H "Sec-WebSocket-Key: dGVzdC1rZXktMTIzNDU2Nzg=" \
  -H "Sec-WebSocket-Version: 13" \
  http://<TARGET>:2718/terminal/ws

# If it returns 101 (Switching Protocols), the endpoint is open without auth
# If it returns 401/403, authentication is enforced (patched or hardened)

# For comparison, test /ws (should always require auth)
curl -s -o /dev/null -w "%{http_code}" \
  -H "Upgrade: websocket" \
  -H "Connection: Upgrade" \
  -H "Sec-WebSocket-Key: dGVzdC1rZXktMTIzNDU2Nzg=" \
  -H "Sec-WebSocket-Version: 13" \
  http://<TARGET>:2718/ws

If /terminal/ws returns 101 while /ws returns 401/403, this is the classic CVE-2026-39987 signature.


Indicators of Compromise

Watch for these signs in your environment:

IndicatorWhere to CheckWhat to Look For
Unauthorized WebSocket connectionsServer/proxy logsConnections to /terminal/ws from unexpected IPs
PTY session creationProcess monitoringUnexpected shell processes spawned by the Marimo server
File accessFile audit logsReads of .env, credential files, or SSH keys
Credential usageCloud provider audit logsAPI calls using keys that were stored in the Marimo environment
Outbound data transferNetwork monitoringUnusual egress traffic from the Marimo host

Investigation commands:

root@kitploit:~
# Check for active WebSocket connections
ss -tnp | grep <MARIMO_PORT>

# Review process tree for unexpected shells
ps aux --forest | grep -A5 marimo

# Check if .env or credential files were recently accessed
stat .env
stat ~/.aws/credentials

# Review cloud provider activity logs for unauthorized access
aws cloudtrail lookup-events --lookup-attributes AttributeKey=AccessKeyId,AttributeValue=<KEY_ID>

# Check for unauthorized outbound connections
netstat -tnp | grep ESTABLISHED | grep -v 127.0.0.1

Remediation

Immediate actions (do these now):

  1. Upgrade to Marimo 0.23.0 or later (pip install --upgrade marimo)
  2. Restrict network access to Marimo instances via firewall rules (bind to localhost or trusted IPs only)
  3. Check for unauthorized connections in your server logs

Short-term (this week):

  1. Rotate ALL credentials that were accessible from Marimo environments (AWS keys, API tokens, database passwords, cloud service accounts)
  2. Audit cloud provider activity logs for unauthorized API calls using potentially compromised credentials
  3. Review .env files and environment variables for any sensitive data that may have been exposed
  4. Check for persistence mechanisms (unauthorized SSH keys, cron jobs, modified startup scripts)

Long-term:

  1. Never expose notebook environments directly to the internet (use VPN or SSH tunnels)
  2. Treat AI/ML development environments as high-security assets (they contain cloud credentials and have code execution capabilities)
  3. Include notebook servers in your regular vulnerability scanning program
  4. Implement network monitoring for notebook server instances with alerting on unexpected connections

References

  • The Hacker News — Marimo RCE Flaw CVE-2026-39987 Exploited Within 10 Hours
  • SecurityWeek — Critical Marimo Flaw Exploited Hours After Public Disclosure
  • BleepingComputer — Critical Marimo Pre-Auth RCE Flaw Now Under Active Exploitation
  • Security Affairs — CVE-2026-39987: Marimo RCE Exploited in Hours After Disclosure
  • CSA Labs — Marimo Pre-Auth RCE: AI Development Toolchain Under Attack
  • GBHackers — Marimo RCE Vulnerability Exploited Within 10 Hours
  • InfoWorld — Critical Flaw in Marimo Python Notebook Exploited Within 10 Hours

Author

Kerem Oruç — Cybersecurity Engineer

  • GitHub: @keraattin
  • Twitter: @keraattin
Download Tool