|

¡Marimo RCE: Explotado en Menos de 10 Horas!

Una vulnerabilidad crítica de ejecución remota sin autenticación en Marimo, plataforma de notebooks Python reactivos, fue explotada por atacantes en menos de 10 horas desde su divulgación el 8 de abril de 2026. El CVE-2026-39987 afecta el endpoint /terminal/ws que no valida credenciales, permitiendo acceso completo a shell interactivo. Equipos de seguridad de Sysdig capturaron un ataque que robó credenciales AWS en 3 minutos. La versión 0.23.0 cierra la vulnerabilidad, pero muchas instalaciones aún no la aplican.

En 30 segundos

  • CVE-2026-39987: endpoint /terminal/ws de Marimo no valida autenticación, RCE pre-autenticado (CVSS 9.3)
  • Timeline: disclosure 8 abril → primer exploit sin PoC público en 9 horas 41 minutos (vs 20 horas en vulnerabilidad Langflow similar)
  • Impacto real: atacante obtuvo shell PTY completo, accedió a .env, robó AWS access keys en 3 minutos
  • Versiones vulnerable: todas antes de 0.23.0 (actualización disponible desde April 2026)
  • Mitigaciones: actualizar, bloquear /terminal/ws con firewall, o restringir acceso a red local

Marimo es una plataforma de notebooks Python reactivos que permite a data scientists e ingenieros de ML escribir, documentar y visualizar código en entorno interactivo. A diferencia de Jupyter, Marimo ejecuta celdas en orden reactivo (como hojas de cálculo) y ofrece terminal integrada WebSocket para debugging. Su popularidad creció porque maneja dependencias automáticamente y se ejecuta en navegador. Lo que casi nadie notó: ese endpoint de terminal era una puerta abierta.

¿Qué es Marimo y por qué importa?

Si alguna vez probaste un notebook de Jupyter y te frustraron los errores de dependencias, las celdas ejecutándose en orden random, o tener que reiniciar el kernel cada cinco minutos, entonces entendés por qué Marimo existe. Es reactivo — cuando cambiás una variable, todo lo que depende de ella se actualiza automático. Es como Excel pero para Python (ponele que sin las frustraciones).

Marimo se usa en equipos de IA y data science porque:

  • Instalación limpia: resuelve dependencias automáticamente en cada sesión
  • Compartible: exporta a HTML estático o app interactiva
  • Debugging rápido: tiene terminal WebSocket integrada para inspeccionar el estado del servidor
  • Hosting simple: corre en cualquier máquina con Python 3.7+ (incluye contenedor Docker)

Y ahí está el tema. Ese terminal WebSocket que parecía una feature conveniente para development? (spoiler: no fue pensado para producción) resultó ser una puerta de servicio que no pedía contraseña.

La vulnerabilidad CVE-2026-39987: especificaciones técnicas

El endpoint vulnerable es `/terminal/ws`. Su función: abrir una sesión WebSocket para interactuar con el shell PTY (pseudo-terminal) del servidor. Problema: no valida que el cliente tenga credenciales válidas.

Mirá el detalle. En el código de Marimo, hay una función `validate_auth()` que protege otros endpoints. Pero cuando la cadena de middleware llega a `/terminal/ws`, esa validación nunca corre. Resultado: cualquiera conectado a la red (o a internet, si el puerto está expuesto) puede mandar un WebSocket upgrade y obtener acceso completo a un shell interactivo en la máquina del servidor. Sin usuario, sin contraseña, sin nada. Raw shell access. Te puede servir nuestra cobertura de ejecutar código Python sin depender de APIs.

CVSS 9.3 (crítico). Vectores de ataque:

  • CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H — Network, Low complexity, No privileges, No user interaction
  • Si el puerto está abierto a internet, cualquiera puede explotarlo sin credenciales desde cualquier lugar
  • Una vez adentro, el atacante hereda los permisos del usuario que corre Marimo (frecuentemente root o servicios de cloud con acceso a secretos)

Versiones afectadas: todas anteriores a 0.23.0. Marimo lanzó el parche el 8 de abril en respuesta al disclosure.

Cómo funciona el exploit: del advisory a la explotación

Esto es lo que impresionó (en el mal sentido) a los investigadores de Sysdig: no había PoC público cuando el atacante ya estaba adentro.

Timeline preciso (según Sysdig TRT):

MomentoEvento
8 abril, ~06:00 UTCMarimo divulga CVE-2026-39987 en GitHub advisory. Descripción: “endpoint /terminal/ws sin autenticación”
17 abril, 15:41 UTCPrimer intento de explotación detectado en wild. Sin PoC público existente
17 abril, 15:45-15:48 UTCOperación de credential theft completada: 3 minutos
vulnerabilidad marimo rce diagrama explicativo

El atacante leyó el advisory (que incluye detalles técnicos del endpoint y por qué falla), escribió un exploit WebSocket en base a esa descripción, conectó, y tuvo shell.

Es un patrón que vimos antes: Langflow tuvo un RCE similar hace poco (CVE-2026-33017), pero ese tomó 20 horas en ser explotado en wild. Marimo lo hizo en menos de la mitad del tiempo. Dicho esto, la diferencia clave es que Langflow era una herramienta más underground — Marimo tiene tracción en comunidades de AI que incluyen grupos de “bug bounty hunters” y adversarios organizados que monitean GitHub 24/7.

Cronología de ataque real: 3 minutos para robo de credenciales

El ataque capturado por Sysdig muestra la velocidad real de daño:

  • Sesión 1: Atacante conecta al `/terminal/ws`, obtiene PTY interactivo. Inmediatamente, lista variables de entorno (`env`) y busca secrets
  • Sesión 2: Localiza archivo `.env` en el directorio de trabajo. Lo lee (`cat .env`). Encuentra AWS_ACCESS_KEY_ID y AWS_SECRET_ACCESS_KEY
  • Sesión 3: Enumera directorios home buscando credenciales adicionales. Chequea `~/.aws/credentials` y `~/.ssh/`
  • Tiempo total: 3 minutos de sesiones interactivas. Ya tiene todo para acceder a la infraestructura AWS de la víctima

Una vez con AWS keys válidas, el atacante puede (sin volver al servidor Marimo) crear instancias EC2, leer S3 buckets, acceder a bases de datos RDS, etc. El daño se multiplica.

Lo interesante acá: no fue un ataque automatizado masivo. Fueron sesiones manuales, exploratorias, sin herramientas fancy. Eso significa que el atacante (o el grupo) revisaba realmente qué había en cada máquina.

Versiones afectadas y estado de disponibilidad del parche

Toda versión de Marimo previa a 0.23.0 es vulnerable. Marimo 0.23.0+ integra validación de autenticación en `/terminal/ws` usando el middleware existente `validate_auth()`.

La buena noticia: el parche existe y está disponible. La mala noticia: adoption es lenta. Muchas instalaciones de Marimo corren en máquinas local dev o notebooks que nunca se actualizan. Equipos que deployaron Marimo en producción hace 6 meses probablemente siguen en versión 0.20.x o anterior (inercia clásica de updates). Ojo con esto. Cubrimos ese tema en detalle en dónde publicar notebooks de forma segura.

Mitigaciones inmediatas: bloqueo del endpoint y firewall

Si tu equipo usa Marimo, tenés cuatro opciones ordenadas por urgencia:

Opción 1: Actualizar a 0.23.0 (ahora mismo)

Es la solución real. Si usás Marimo en producción, ya debería estar en roadmap. Versiones anteriores a 0.23.0 son RCE 0day activamente exploradas. No esperes a la próxima reunión de planning.

“`bash pip install –upgrade marimo==0.23.0

Opción 2: Bloquear `/terminal/ws` con firewall o proxy (mientras actualizás)

Si no podés actualizar mañana, filtrá el endpoint. En nginx:

  • Agregá un `location ~ ^/terminal/ws { deny all; }` antes del bloque proxy
  • Usuarios no van a poder usar la terminal de Marimo, pero sí van a poder ejecutar notebooks normales
  • Es un workaround temporal mientras preparás la actualización

Opción 3: Restringir acceso de red a máquinas que corren Marimo

Si Marimo solo es usado internamente, limitá el acceso al rango de IPs internas. Los ataques capturados por Sysdig fueron desde IPs externas, así que si cerrás el acceso a red pública, reducís significativamente el riesgo (aunque un insider podría seguir explotándolo).

Opción 4: Rotar credenciales almacenadas en servidores Marimo

Si sospechas que alguien explotó la vulnerabilidad:

  • Rotá todos los AWS keys, API tokens, secrets en .env de servidores Marimo
  • Reviá logs de acceso para detectar si alguien entró al /terminal/ws (buscar WebSocket upgrades sin User-Agent válido)
  • Auditá cambios en IAM, S3, RDS en AWS con CloudTrail

Monitoreo y detección de intentos de explotación

Aunque actualices, valía la pena prepararse para detectar intentos. Herramientas:

Falco (reglas Sysdig)

Sysdig publicó reglas Falco que detectan patrones de explotación de CVE-2026-39987. Si corres Falco en tus servidores, instalá las reglas más recientes y buscá:

  • Conexiones WebSocket a `/terminal/ws` sin sesión autenticada previa
  • Ejecución de shell commands desde contenedor Marimo (especialmente `cat`, `env`, `ls` en directorios sensibles)
  • Acceso a archivos `.env` desde procesos Marimo

WAF / IDS

Un Web Application Firewall o Intrusion Detection System puede bloquear patrones de ataque conocidos. CloudFlare, AWS WAF, y herramientas open-source como Suricata tienen reglas para RCE en endpoints sin autenticación. Mantené las firmas de IDS actualizadas.

Logs de acceso

Revisá access logs buscando requests a `/terminal/ws` desde IPs no reconocidas. Marimo no loguea actividad de terminal por defecto, así que el único rastro es el WebSocket upgrade en access logs del reverse proxy (nginx, Apache, etc.). Sobre eso hablamos en herramientas populares en ciencia de datos.

Errores comunes al proteger Marimo

Error 1: asumir que Marimo solo se usa en desarrollo

Equipo dice “bueno, Marimo es una herramienta dev, no la exponemos a internet”. Realidad: alguien corrió un Marimo en producción para análisis de datos en tiempo real, lo expuso en AWS, y nadie lo notó. Marimo es fácil de deployar, así que termina en producción sin que DevOps lo sepa. Asumir que está aislado es peligroso.

Error 2: actualizar Marimo sin revisar versiones de dependencias

Marimo 0.23.0 requiere Python 3.10+ en algunos setups. Si tu virtualenv es 3.9, el upgrade falla silenciosamente. Testea la actualización en staging primero. Mínimo reviá `pip install marimo==0.23.0` localmente antes de deployar.

Error 3: bloquear `/terminal/ws` pero dejar otros endpoints sin protección

El foco está en `/terminal/ws`, pero hay otros endpoints de Marimo que podrían tener lógica vulnerable. Si necesitás exponer Marimo a internet, pon un proxy de autenticación (OAuth, API key, Basic Auth) enfrente de TODO el servicio, no solo del endpoint de terminal.

Preguntas Frecuentes

¿Qué es el CVE-2026-39987 exactamente?

CVE-2026-39987 es una vulnerabilidad de ejecución remota sin autenticación en Marimo. El endpoint `/terminal/ws` no valida credenciales, permitiendo a cualquiera conectarse y ejecutar comandos de shell en la máquina del servidor. Severidad CVSS 9.3 (crítica). Afecta todas las versiones antes de 0.23.0.

¿Cómo hacen los atacantes para encontrar instancias de Marimo expuestas?

Escanean internet con herramientas como Shodan buscando el banner HTTP de Marimo, o simplemente proban en IPs aleatorias si responde en puerto 3000 o 8000 (puertos típicos de Marimo). Una vez identifican un servidor, intentan conectar a `/terminal/ws`. No necesitan saber que es Marimo de antemano. En plataformas para alojar código ejecutable profundizamos sobre esto.

¿Puedo mitigar sin actualizar Marimo?

Sí, pero es temporal. Opciones: (1) bloquea el endpoint `/terminal/ws` con firewall/proxy, (2) restringí acceso a red local, (3) deployá Marimo sin exponer a internet. Pero eventualmente tenés que actualizar — eso no es negociable si querés que Marimo sea seguro.

¿Si actualizo a 0.23.0, estoy 100% seguro?

Del CVE-2026-39987, sí. Pero siempre hay nuevas vulnerabilidades por descubrir. Mantené Marimo actualizado, chequeá el changelog regularmente, y seguí mejores prácticas: expone Marimo solo a red local, detrás de proxy autenticado, o restringido por IP. Una herramienta dev no debería estar abierta a internet sin protección adicional.

¿Cómo detecto si alguien explotó la vulnerabilidad en mi servidor?

Buscá en los logs del reverse proxy (nginx, Apache) intentos de WebSocket upgrade a `/terminal/ws`. Si ves requests desde IPs desconocidas, revisá los logs del servidor Marimo mismo (si existen) para actividad de shell. Auditá cambios en archivos `.env` o credenciales. Si la máquina tiene el servidor expuesto a internet y no actualizaste, asumiría lo peor y rotaría credenciales de inmediato.

Conclusión

El CVE-2026-39987 de Marimo es un recordatorio de por qué herramientas de development nunca deberían correr sin protección en producción (o expuestas a internet). La vulnerabilidad en sí no es sofisticada — es validación de autenticación faltante — pero el impacto es máximo porque Marimo típicamente corre donde están los datos y secretos.

Si tu equipo usa Marimo: actualiza a 0.23.0 ahora. No esperes. Los ataques comenzaron menos de 10 horas después del disclosure, así que asumimos que la mayoría de instalaciones vulnerables ya fueron identificadas y están en lista de scanning de atacantes.

Si no podés actualizar inmediatamente, bloquea `/terminal/ws` con firewall y rota credenciales. Si Marimo está en internet sin protección, que sea acceso restringido (VPN, auth) o completamente offline.

Y si sospechas que un servidor fue comprometido: log everything, rota secrets, auditá cambios en IAM y acceso a datos. Tres minutos fue todo lo que un atacante necesitó para llevarse credenciales AWS en el caso capturado por Sysdig. No esperes que pase sin ti notarlo.

Fuentes

Similar Posts