El comando empezaba con npm install
El 24 de agosto de 2026, el equipo CTRL de Cato Networks publicó una campaña que compra resultados patrocinados de Google para “codex macos download”, lleva a los desarrolladores a una página de Google Sites disfrazada del portal Codex de OpenAI y les pide que peguen en el Terminal un comando cuya primera línea es un npm install real de Codex. Todo lo que sigue a esa línea es base64. Bromure Agentic Coding nunca manda a nadie a buscar un agente de codificación: el comando de instalación es una cadena fija en el propio catálogo de imágenes de Bromure, se ejecuta dentro de una VM Linux desechable, las credenciales que hay ahí son señuelos y, con el tráfico saliente no coincidente denegado, las tres peticiones del cargador nunca salen de la máquina.
Durante dos años la industria ha construido controles para lo que instala un agente de codificación. Esta campaña retrocede un paso y envenena cómo instalas el agente de codificación. Ese paso no tiene registro, ni lockfile, ni atestación de procedencia. Tiene una caja de búsqueda, una página que parece correcta y tus propias manos sobre el teclado.
Un desarrollador quiere probar el CLI Codex de OpenAI en su Mac, así que teclea
codex macos download en Google. El primer resultado es patrocinado y está por
encima del propio anuncio de OpenAI. Lleva a un portal de descarga impecable,
con el logotipo correcto y la tipografía correcta, alojado en
sites.google.com. La página dice: abre el Terminal, pega esto.
Lo pega. El comando empieza con npm install y el nombre del paquete es
correcto.
El 24 de agosto, el equipo de investigación CTRL de Cato Networks publicó el análisis de esa campaña, recogido el mismo día por Infosecurity Magazine, SiliconANGLE y Techzine. La carga final es un ladrón de información para macOS. Lo que merece el análisis es la entrega.
Google alojaba la página. El señuelo lo alojaba otro.
Google Sites es un constructor de sitios. Cualquiera con una cuenta obtiene una página en un dominio de Google, y el certificado, el candado y la primera mitad de la URL pertenecen todos a Google. Esa es la confianza alquilada.
La página en sí no contiene nada. Cato no encontró en ella código malicioso
alguno. El señuelo llega dentro de un iframe apuntado a la infraestructura
del atacante, enrutado, según el análisis de Cato, a través de un proxy de
contenido estático de Google, de modo que incluso el segundo salto parece Google
buscando algo. Techzine nombra dos de los hosts del iframe: bright-links[.]com
y swiftsaverfin[.]com.
Esa separación les compra dos cosas a los operadores. La página visible nunca cambia, así que nunca dispara un sistema de reputación ni vuelve a revisarse, y cambian las cargas al otro lado del iframe cuando les apetece. Cato contó tres conjuntos de infraestructura distintos, y el tercero reutilizaba un host de iframe del primero.
El resto se lee como una operación madura de fraude publicitario. Los señuelos
vivos están bajo una ruta ofuscada, /codexx/, mientras que /codex/ sirve algo
inofensivo. Los operadores toman huellas de los visitantes, y todo lo que no sea
un objetivo macOS plausible ve contenido benigno, que es su respuesta a
investigadores y sandboxes. Los dominios rotan. Las URL de carga varían.
La primera línea era real
ClickFix no te sirve un archivo. Te da una instrucción y deja que seas tú quien lleve la carga al otro lado de la frontera. Como dice Techzine, “no se descarga ningún archivo que una solución antivirus pudiera bloquear”.
El comando pegado empieza con una cadena npm install de apariencia legítima
para Codex. Ese es todo el truco. Un desarrollador a punto de instalar un CLI de
Node ve npm install, ve el nombre del paquete que buscó, y su cerebro archiva
la línea como correcta. El blob base64 que sigue está a un operador de shell de
distancia, en la misma línea, más allá del pliegue de la caja de copiado. Uno no
lee la segunda mitad de un comando cuya primera mitad es el comando que
esperaba.
Descodificado, descarga un script remoto y lo canaliza a zsh. Siguen tres
etapas.
La etapa uno es un script de shell relleno de código muerto y variables sin
usar, que envuelve un blob codificado que acaba entregado a eval. El relleno
existe para derrotar la coincidencia de patrones y para que el humano que ojea el
archivo se rinda.
La etapa dos emite una baliza de vuelta al atacante con un parámetro
event=pasted antes de hacer ninguna otra cosa. Eso es un acuse de recibo.
Alguien al otro lado está midiendo la tasa de pegado de sus páginas de aterrizaje,
igual que un responsable de marketing mide conversiones.
La etapa tres descarga el binario a /tmp/helper, ejecuta xattr -c para
quitar el atributo de cuarentena que macOS adjunta a todo lo que llegó de la red,
que es lo que suprime el aviso de Gatekeeper, lo marca como ejecutable y lo
lanza. El binario es un Mach-O universal, así que corre tanto en Intel como en
Apple Silicon.
Cato señala que los operadores siguen desarrollando el cargador. Las muestras anteriores usaban base64 con compresión; las más nuevas usan contenedores gzip cifrados con AES cuya clave se reensambla a partir de variables repartidas por el script.
Para la carga final, Cato vincula el marco de entrega con Atomic macOS
Stealer: la estructura de la URL del cargador, la forma de la petición de
telemetría, la ruta de preparación /tmp/helper, la eliminación de xattr, las
URL de carga con temática de actualización. Califican el solapamiento de fuerte y
consistente y se detienen antes de nombrar el binario, que es la decisión
correcta y conviene conservar cuando uno repite la historia.
El paso aguas arriba de los escáneres
Alinea los controles que la industria lleva dos años construyendo para los agentes de codificación. Escaneo de reputación de registros. Lockfiles y hashes de integridad. Procedencia de compilación y atestación. SBOM. Puertas de edad mínima para versiones nuevas de paquetes. Análisis estático del código generado. Todos funcionan, y todos parten de la misma suposición: el desarrollador ya tiene una cadena de herramientas que funciona, y el riesgo está aguas abajo, en lo que hace con ella.
Esta campaña se sitúa aguas arriba de todo eso. La falsificación aquí es el agente mismo, y llega antes de cualquier registro, antes de cualquier lockfile, en un comando que el desarrollador teclea con sus propias manos en su propio terminal. Un escáner no tiene artefacto que puntuar, porque el artefacto es una frase en una página web.
La segmentación es la otra mitad de la economía. Quien puja por codex macos download está comprando la máquina de una persona que está, en ese preciso
momento, montando un agente de codificación: una máquina que dentro de una hora
contendrá un token de API, una clave SSH, un archivo ~/.aws/credentials y un
PAT de GitHub, todo lo cual un ladrón de información sabe encontrar. El momento
de la instalación es la hora más barata para estar ahí.
Ya hemos cubierto lo inverso: con FakeGit y AgentBaiting es el agente el que busca y le tiende al humano los pasos de instalación. Aquí es el humano el que busca. Ambos funcionan porque descubrir-y-pegar es como se instala el software, y no hay escáner en ninguno de los dos extremos de ese bucle.
De dónde sale el comando de instalación
Bromure Agentic Coding no tiene ese bucle, y la razón está en de dónde viene el agente.
Tú no sales a buscar un agente de codificación. Codex es un interruptor en el panel Agents de un perfil, junto a Claude Code y Grok Build. Actívalo, elige cómo se autentica, y el agente está ahí en la siguiente sesión, corriendo en una pestaña de kitty dentro de la VM del perfil.
Detrás de ese interruptor hay una cadena fija. Bromure aprovisiona su imagen base desde su propio catálogo, y la entrada de Codex es una línea:
npx --yes @socketsecurity/cli npm install -g --silent @openai/codex
Claude Code es @anthropic-ai/claude-code con el mismo patrón, Kimi Code es
@moonshot-ai/kimi-code. Los nombres de paquete están compilados dentro de la
aplicación, no descubiertos. El registro es registry.npmjs.org, no el host que
proponga un iframe. La instalación va envuelta por el CLI de socket.dev, y la
petición sale por el proxy MITM del host, donde se aplican las políticas de
Supply Chain del perfil: la puerta de edad de dos días activa por defecto,
más las consultas OSV, el filtrado por socket.dev o Delpi y la eliminación de
scripts de instalación que puedes activar.
Ese camino no tiene resultado de búsqueda ni página que suplantar. El canal que el atacante pagó por envenenar está ausente del flujo de trabajo, y ausente no es un control que haya que acordarse de operar.
Ahora pégalo de todas formas
La arquitectura tiene que sobrevivir al día en que alguien la ignora. Coge la campaña, dale la victoria, y hazla atravesar un perfil: alguien encuentra el portal falso, copia el comando y lo pega en el terminal donde hace trabajo de agentes, que en Bromure Agentic Coding es una pestaña de kitty dentro de la VM.
El binario no se ejecuta. Un Mach-O universal es un ejecutable de macOS. El
invitado es Ubuntu. xattr no es un comando de Linux, y /tmp/helper es una
ruta en un disco de sistema que existe para ser descartado. Recursos →
Almacenamiento te da Borrar la carpeta personal… para /home/ubuntu y
Restablecer a la base… para volver a clonar el disco de sistema del espacio de
trabajo desde la imagen base compartida y de solo lectura.
Las tres peticiones no salen. Cada etapa de esa cadena necesita la red: la
URL descodificada en base64 que trae la etapa uno, la baliza event=pasted y la
descarga de la carga. Guardrails → Conexiones salientes es una tabla de
reglas al estilo pf: acción, protocolo (tcp, udp, web, any), host o
CIDR, puertos, y para web una lista de métodos HTTP, evaluadas de arriba abajo,
gana la primera coincidencia, con Tráfico no coincidente en Permitir o Denegar.
Ponlo en Denegar y enumera los hosts que tu trabajo necesita.
bright-links.com no es uno de ellos. Bromure aplica la tabla en el lado del
host, en el conmutador virtual y en el proxy, así que nada de lo que el invitado
haga con su propio entorno cambia la respuesta.
La etapa dos es la que merece un momento de reflexión. event=pasted es la
métrica de conversión del operador, el ping que le dice que una página de
aterrizaje está funcionando, y cuánto. Cuando esa petición muere en el host, no
recibe un informe de infección fallida. Recibe silencio, que se lee como una
impresión publicitaria que nunca convirtió.
El robo devuelve marcadores de posición. Un ladrón de la clase de Atomic va a
por datos del navegador, monederos y, en una máquina de desarrollo, credenciales.
En un perfil Bromure los valores reales nunca entran en la VM. Las claves de API
genéricas son falsificaciones brm_… exportadas como variables de entorno y
sustituidas en el cable por el proxy del host. El kubeconfig es sintético, con
certificados de cliente desechables. Las peticiones a AWS se vuelven a firmar en
el host, de modo que cualquier cosa que rodee el proxy recibe
InvalidSignatureException. ~/.docker/config.json guarda un blob base64 falso.
Las claves SSH privadas no están ahí para leerse:
nunca lo estuvieron. Activa Requerir
aprobación para usar por credencial y cada sustitución se convierte en un
diálogo del host con una concesión acotada en el tiempo: cinco minutos, una hora,
el resto de la sesión. Un perfil comparte como mucho ocho carpetas que hayas
elegido, así que el resto del Mac no está a un recorrido de directorios de
distancia.
La correlación ya está en tu pantalla. La propia conclusión de Cato es que ninguna etapa aislada de esta campaña la delata; detectarla exigió correlacionar juntas la entrega por búsqueda patrocinada, el contenido web incrustado, la ejecución en el Terminal y la actividad saliente. Ese es un problema difícil cuando tus pruebas están repartidas entre un navegador, un shell y una sonda de red. En un perfil es una sola ventana: el Registro de seguridad (Ventana → Registro de seguridad…) es una única tabla cronológica, del lado del host, de veredictos de paquetes, decisiones del cortafuegos, sustituciones de credenciales y detecciones de inyección de prompts. El código invitado no puede editarla, porque el código invitado no puede alcanzarla.
Actívalo
La puerta de edad viene activa por defecto a dos días. Las demás capas son ajustes, y valen dos minutos: Guardrails → Conexiones salientes, con Tráfico no coincidente en Denegar y una lista de permitidos para los hosts que tu trabajo necesita. Supply Chain → Comprobación de vulnerabilidades OSV, más el filtrado por socket.dev o Delpi si tienes una clave, y la eliminación de scripts de instalación. Credenciales → Requerir aprobación para usar en todo lo que pueda gastar dinero o borrar datos. Luego deja la ventana del Registro de seguridad abierta en una segunda pantalla durante una semana y mira con quién hablan tus compilaciones.
Los resultados de búsqueda patrocinados van a seguir siendo la puerta de entrada, y los constructores de sitios en dominios de confianza van a seguir alojando el porche. Google tirará estas páginas y subirán otras tres, porque la economía son unos pocos dólares por clic contra una estación de trabajo de desarrollo con credenciales de nube dentro. Instala Bromure Agentic Coding, habilita tus agentes desde el editor de perfiles en lugar de una página de descarga, y deja que el próximo comando pegado aterrice en una máquina construida para tirarse a la basura.