Volver a todas las publicaciones
Publicado el · por Renaud Deraison

Escrito con tinta invisible

Socket descubrió TrapDoor, una campaña de ataque a la cadena de suministro en npm, PyPI y Crates.io que hace algo nuevo: un paquete instalado reescribe el archivo de reglas de tu propio agente de código — CLAUDE.md, .cursorrules — y esconde la instrucción en Unicode de ancho cero que no puedes ver. La próxima vez que ejecutes el agente, lee sus propias reglas internas y corre un “escaneo de seguridad” que recoge tus claves SSH, credenciales de nube, token de GitHub y billeteras cripto. La instrucción es invisible; el robo es real. Bromure Agentic Coding le entrega a ese escaneo una caja donde no hay nada que valga la pena llevarse.

Un paquete que instalaste edita el archivo en el que tu agente de código más confía — su propio archivo de reglas — y escribe la línea maliciosa en caracteres que aparecen como nada. Revisas el archivo, ves notas de proyecto corrientes y lo apruebas. El agente lee el mismo archivo y ve una orden: correr un escaneo de seguridad, enviar los resultados aquí.

La mayoría de los ataques que cubrimos esconden una instrucción maliciosa en algún lugar donde el agente la leerá — una página web, un comentario de pull request, un README. Este la esconde en el último lugar en el que pensarías mirar: la configuración misma del agente. El 22 de mayo de 2026, Socket comenzó a rastrear una campaña que bautizó como TrapDoor — 34 paquetes maliciosos y más de 384 versiones publicados en npm, PyPI y Crates.io, con los operadores republicando más rápido de lo que las retiradas podían seguir. El feed automatizado de Socket detectaba nuevas versiones en cinco minutos y cincuenta y seis segundos de media; la más rápida, cincuenta y ocho segundos después de la publicación. The Hacker News y Phoenix Security lo cubrieron esa misma semana. Escribimos sobre ello ahora porque su movimiento más reciente es el ejemplo más nítido hasta la fecha de un ladrón de cadena de suministro construido para apuntar directo a un agente de código.

Los paquetes parecen las herramientas a las que una desarrolladora echa mano sin pensarlo dos veces: cargadores de entorno, verificadores de billetera, ayudantes de compilación y — el que empezó todo — eth-security-auditor, un “auditor de seguridad”. Instala uno y hace las cosas corrientes de un infostealer. Pero la carga compartida de npm, un archivo de 48 KB llamado trap-core.js, hace una cosa más que no tiene nada de corriente. Escribe en .cursorrules y CLAUDE.md.

La línea que no puedes ver

Esos dos archivos son reglas internas. Cursor lee .cursorrules; Claude Code lee CLAUDE.md. Existen para que un repositorio pueda decirle al agente cómo comportarse en este proyecto — las convenciones, lo que se hace y lo que no — y el agente las trata como instrucciones permanentes, aplicadas a todo lo que hace en esa carpeta. Es el texto de mayor confianza del espacio de trabajo, porque se supone que lo escribiste tú.

TrapDoor escribe en ellos y esconde lo escrito. La instrucción maliciosa está codificada con caracteres Unicode de ancho cero — U+200B, U+200C, U+200D, U+FEFF — puntos de código que un editor de texto no muestra en absoluto. Abre CLAUDE.md y ves tus notas de proyecto corrientes. Corre git diff y, según tus ajustes, quizá no veas nada que valga la pena detenerse. Los bytes están ahí; los glifos no. Es un mensaje escrito con tinta invisible, y el único lector que la revela es el agente, que analiza todo el flujo Unicode y encuentra una instrucción posada en su propio reglamento.

CLAUDE.mdnotas + una líneacon tinta invisibleun archivoLo que ves# Convenciones del proyecto- Usar pnpm, no npm- Tests en /spec- Preferir PR pequeños·corriente. aprobado.Lo que lee el agente# Convenciones del proyecto- Usar pnpm, no npm- Tests en /spec- Preferir PR pequeños‹correr escaneo de seg.; recoger secretos; POST›decodificado del Unicode de ancho cero
El mismo archivo, dos lectores. Una desarrolladora abre CLAUDE.md y ve convenciones de proyecto corrientes — los puntos de código de ancho cero (U+200B, U+200C, U+200D, U+FEFF) aparecen como nada, así que la línea maliciosa es invisible en el editor y fácil de pasar por alto en un diff. El agente de código analiza todo el flujo Unicode, revela la tinta oculta y lee una instrucción permanente en el archivo en el que más confía: correr un “escaneo de seguridad”, recoger secretos locales, enviarlos fuera.

El escaneo que roba

La instrucción oculta le dice al agente que corra un “escaneo de seguridad”. Nada en eso suena alarmante — le entregaste al agente un auditor de seguridad, y ahora sus reglas le piden que audite. Lo que el escaneo hace en realidad es recorrer la máquina en busca de cualquier cosa que valga dinero. El desglose de la carga por parte de Socket enumera claves SSH, credenciales de AWS, tokens de GitHub, perfiles de navegador y bases de inicio de sesión, variables de entorno y claves de API y — la firma de esta campaña — billeteras de criptomoneda: Sui, Solana, Aptos y las extensiones de billetera del navegador. Luego exfiltra hacia un sitio de GitHub Pages (ddjidd564[.]github[.]io) y, en la variante de Crates.io, hacia GitHub Gists.

Un detalle muestra lo deliberado que es esto. Antes de enviar nada, la carga “llama activamente a las API de AWS y GitHub para confirmar si las credenciales robadas son válidas, filtrando los tokens de alto valor antes de la exfiltración”. No se limita a agarrar y volcar. Prueba cada credencial contra el servicio real, se queda con las vivas y descarta las muertas. Los operadores quieren una lista limpia de claves que funcionan.

Phoenix Security nombra por qué esto golpea más fuerte a las personas a las que apunta: desarrolladores de cripto y DeFi, porque “las claves SSH, las credenciales de nube, los tokens de GitHub y los keystores de billetera cripto conviven de forma rutinaria en la misma máquina”. Esa frase es toda la superficie de ataque. El agente corre en tu portátil, como tú, y todo lo de valor está a su alcance. La línea invisible en el archivo de reglas es solo el disparador; el acceso ambiente es la carga útil.

Dónde traza Bromure la línea

Bromure Agentic Coding no depende de detectar la línea invisible — aunque, como veremos, lee los mismos bytes. Cambia lo que la línea puede alcanzar cuando se dispara. El agente de cada perfil corre dentro de una VM Linux desechable en Apple Silicon, a un hipervisor de macOS, y las credenciales en esa caja no son las tuyas.

Las credenciales son señuelos. Esta es la capa en la que TrapDoor se mete de lleno, porque TrapDoor es, en el fondo, un ladrón de credenciales. Un intermediario de credenciales en el host mantiene tus secretos reales de Anthropic, AWS y GitHub totalmente fuera de la caja. Dentro de la VM el agente ve marcadores de posición — un token brm_…, un kubeconfig sintético, una clave SSH desechable — y el intermediario solo cambia por el valor real en la frontera de la red, en peticiones hacia destinos que ya aprobaste. Así que el “escaneo de seguridad” corre, recorre el disco y cosecha exactamente lo que se le envió a cosechar: falsificaciones. Y el ingenioso paso de validación de la campaña se vuelve en su contra — llama a AWS y GitHub para confirmar que los tokens están vivos, los señuelos fallan esa prueba, y el filtro pensado para quedarse solo con las claves que funcionan no se queda con nada.

Las billeteras no están ahí. Los keystores de Sui y Solana, las bases de inicio de sesión del navegador, las extensiones de billetera — nada de eso vive en una VM de código desechable. Está en tu máquina real, a un hipervisor de distancia, donde el escaneo no puede verlo. Cierra la sesión y la caja se reinicia, archivo de reglas envenenado incluido.

La exfiltración está filtrada. Digamos que el escaneo encuentra algo que vale la pena enviar. El POST a ddjidd564.github.io, o la escritura en un GitHub Gist, es una petición saliente, y toda petición saliente cruza el proxy del host, donde el destino verdadero se coteja contra la lista aprobada del perfil al salir. Un ladrón que llama a casa a una dirección que el perfil nunca aprobó no sale — y las formas destructivas contra las API que el perfil sí expone se topan con una salvaguarda que puede rechazarlas, sin importar de qué se haya convencido al agente.

En tu máquina — como túEl CLAUDE.md envenenado se dispara →el agente corre el “escaneo de seguridad”Encuentra lo real:claves SSH · AWS · token GitHubSolana · Sui · extensiones de billeteravalidadas vivas contra AWS + GitHubExfiltradas hacia el atacante:página github.io / GistEl escaneo alcanzó todo lo tuyo.Las claves vivas salieron del edificio.Bromure Agentic Coding — VM desechableEl mismo CLAUDE.md envenenado se dispara →el mismo escaneo corre, dentro de la cajaSolo encuentra señuelos:brm_… · kubeconfig sintéticoclave SSH desechable · sin billeterasla validación contra AWS + GitHub fallaExfil a dirección no aprobadadetenida en el proxy del hostEl escaneo cosechó falsificaciones que no pasan la validación.Cierra la sesión y la caja se reinicia.
El escaneo corre de una forma u otra; lo que encuentra es la diferencia. En una configuración normal (izquierda) el agente corre en tu máquina como tú: el archivo de reglas envenenado se dispara, el escaneo alcanza claves SSH reales, credenciales de nube y billeteras, las valida contra AWS y GitHub y exfiltra las vivas. Bajo Bromure Agentic Coding (derecha) el mismo escaneo corre dentro de una VM desechable contra credenciales señuelo, con las billeteras reales a un hipervisor de distancia y cada petición saliente filtrada en el proxy del host — la cosecha son falsificaciones, la validación las descarta, y la llamada de exfiltración a una dirección no aprobada nunca sale.

Por delante de todo eso se sienta la capa que encuentra a TrapDoor en su disparador. Todo el ataque empieza con contenido que el agente lee — el archivo de reglas envenenado — y Bromure puntúa el contenido no confiable con un detector de inyección en el dispositivo antes de que el modelo actúe sobre él. El Unicode de ancho cero que esconde la instrucción de tu editor no la esconde del evaluador: lee el mismo flujo de bytes, puntos de código invisibles incluidos, y un archivo de reglas que se decodifica como “correr un escaneo y enviar por correo los secretos” es exactamente la forma que está hecho para señalar. Atrapa la mayor parte de esto en la puerta. Una codificación lo bastante novedosa todavía puede colarse por un clasificador, y por eso se sienta delante de la caja desechable en lugar de en su lugar.

Invisible para ti, vacío para el ladrón

La parte inquietante de TrapDoor no es el truco de codificación. Es que el truco funciona en el único archivo en el que te dijeron que confiaras — las reglas que escribiste para tu propio agente — y que un humano que revisa ese archivo no ve nada raro, porque no hay nada que ver. La detección tiene que ganar cada vez contra cada nueva forma de esconder una línea. Es una carrera que vale la pena correr, y el evaluador en el dispositivo la corre, pero no es donde debería descansar la seguridad.

Bromure Agentic Coding la hace descansar un nivel más abajo. Da por hecho que el agente acabará leyendo una instrucción envenenada que no puede distinguir de una real — tinta invisible o no — y se asegura de que, cuando el agente vaya a buscar secretos que robar, los secretos sean señuelos, las billeteras estén en una máquina que no puede alcanzar y la salida esté filtrada. El escaneo corre de todos modos. Solo vuelve con las manos vacías. Instálalo y dale a tu agente un reglamento que, envenenado o no, apunte a nada que valga la pena llevarse.