Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
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.

FeedsContactPrivacy© 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.

1175 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.

  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:

  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.

# /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:

Download Tool