CVE-2026-39987 — Marimo pre-auth RCE
marimo before 0.23.0 exposes a pre-auth remote code execution path on
/terminal/ws. The endpoint accepted WebSocket connections without validating
authentication, allowing an unauthenticated attacker to obtain a PTY shell and
run arbitrary commands.
NVD shows this CVE was added to CISA’s KEV catalog on 2026-04-23, which means active exploitation evidence exists and remediation should be expedited. Treat a reachable vulnerable notebook server as an incident candidate, not just a dependency bump.
When to use it
Use this recipe when a repository installs, images, deploys, or documents
Marimo notebooks, shared notebook servers, demos, devcontainers, Codespaces, or
remote workspaces. It is designed for source-code/deployment remediation,
pre-auth RCE exposure review, notebook network-boundary hardening, credential
rotation assessment, and evidence that vulnerable /terminal/ws endpoints are
not reachable.
Inputs
- Marimo version, Python dependency files, lockfiles, notebook images, devcontainer/CI/demo configs, launch commands, reverse-proxy policy, and SBOM or generated dependency reports.
- Source/config paths that start Marimo, expose ports, enable terminal features, forward localhost, mount cloud/model/package/repository credentials, or document notebook access.
- Regression or deployment checks for patched versions, authenticated access,
private network binding, no exposed terminal endpoint, and safe dependency
policy without probing
/terminal/ws. - Boundary evidence: notebook users, exposed URLs, forwarded ports, runtime secrets, incident-review owner, image owners, logs, and rollout owner.
Affected versions
- Vulnerable:
marimo< 0.23.0 - Fixed:
marimo>= 0.23.0
Indicator-of-exposure
marimois installed at a vulnerable version.- The service is reachable from untrusted networks.
- Notebook or terminal functionality is exposed to shared users / internet.
Quick checks:
python -m pip show marimo
python - <<'PY'
import marimo
print(marimo.__version__)
PY
ss -lntp | rg ':2718|:8080|:80|:443'
Windows:
python -m pip show marimo
python -c "import marimo; print(marimo.__version__)"
netstat -ano | findstr ":2718 :8080 :80 :443"
Do not connect to /terminal/ws, attempt to obtain a shell, or print runtime
environment variables during triage.
Remediation strategy
- Upgrade immediately to
marimo>=0.23.0in every manifest, lockfile, image, notebook environment, and deployment artifact controlled by the repository. - Place the service behind strong authentication and reverse-proxy policy.
- Restrict network reachability (VPN / private subnet / IP allow-list).
- Add a non-exploit regression check that fails on resolved
marimo <0.23.0. - Rotate credentials and secrets available to the marimo runtime if exposure was internet-facing or reachable by untrusted users.
The prompt
You are remediating CVE-2026-39987 (Marimo pre-auth RCE) in this repository or
runtime image. Produce exactly one of:
1. A reviewer-ready PR that upgrades marimo to a fixed version and adds basic
hardening controls.
2. TRIAGE.md if no safe patch path exists in this codebase.
## Rules
- Fix only CVE-2026-39987 scope.
- Prefer the smallest safe version bump to `>=0.23.0`.
- Do not auto-merge.
- If internet-exposed runtime was vulnerable, include an incident-response
checklist in the PR body.
## Steps
1. Detect current marimo version from lockfiles + environment metadata.
2. If marimo is absent or already `>=0.23.0`, stop with a short triage note.
3. Update dependency manifests and lockfiles to a fixed marimo version.
4. Search for marimo launch points and add a hardening note (auth + network
boundary) in ops docs or deployment manifest comments, without unrelated
refactors.
5. Add safe regression coverage or a CI/deploy guard that rejects marimo
versions below `0.23.0` without probing `/terminal/ws`.
6. Run project tests/lint and any dependency/security scans.
7. Output:
- PR title: `fix(sec): remediate CVE-2026-39987 in marimo`
- PR body must include: affected version, fixed version, test output summary,
whether the server was network-reachable, and operator follow-ups
(credential rotation if exposed).
## Stop conditions
- Patch would require unsupported major stack migration.
- No lockfile / deterministic dependency mechanism exists.
- Verification would require connecting to `/terminal/ws`, obtaining a shell,
or exposing runtime secrets.
- Tests fail due to unrelated pre-existing failures.
Output contract
- A reviewer-ready PR or change request that upgrades Marimo, refreshes dependency/image artifacts, hardens notebook exposure, adds version/exposure checks, and documents credential/operator review.
- Or a
TRIAGE.mdfile that lists inspected dependencies/images/launchers, owner, observed version, network exposure boundary, required fix, and residual risk. - The output must include exact validation commands and must not connect to
/terminal/ws, obtain shells, print environment variables, or expose runtime secrets.
Verification — what the reviewer looks for
- Lockfile, manifest, image metadata, and generated dependency reports pin
marimoto>=0.23.0. - No vulnerable marimo version remains in the dependency tree.
- CI or deployment checks fail closed on
marimo <0.23.0. - Tests/lint are green or failures are clearly pre-existing.
- PR includes runtime hardening follow-ups if service was internet-reachable.
Watch for
- Updating a local notebook environment while a remote dev image, shared
workspace, or demo container still installs
marimo <0.23.0. - Treating localhost binding as safe when Codespaces, devcontainers, SSH tunnels, or proxy previews forward the port.
- Running marimo with cloud, model-provider, package, or repository-write tokens in the same environment used for interactive notebooks.
- Verification that connects to
/terminal/wsor prints runtime environment values instead of checking version and launch configuration safely.
Related recipes
- Source code attack surface map
- Source code secrets and data exposure audit
- Source code supply chain build integrity audit
- NIST SSDF repository evidence check