Tu agente de código fijó el commit. Nunca comprobó dónde había aterrizado

21 de septiembre de 2026
11 min read

21 de septiembre de 2026
11 min read
Hay un tipo de hallazgo de seguridad que vale más que su puntuación de severidad, porque el mecanismo te enseña algo aplicable en otros sitios. Este es uno de esos.
Los detalles proceden de la cobertura de la divulgación de AIR por The Register, Help Net Security y Cyber Security News. El estado de los parches y las posiciones de los fabricantes son los reportados en el momento de la divulgación y pueden haber cambiado; el apartado 7 dice qué no estoy afirmando. La lectura del mecanismo, y todo lo que va del apartado 4 en adelante, es mía.
El 17 de septiembre de 2026, los investigadores de AIR publicaron Plugin4Shell: un fallo de ejecución remota de código sin un solo clic en los sistemas de plugins de cuatro grandes agentes de código de IA. Lo encontraron en mayo de 2026, construyeron exploits de prueba funcionales contra los cuatro y lo comunicaron a los fabricantes en junio.
Estado según lo reportado en el momento de la publicación:
| Agente | Estado |
|---|---|
| Claude Code | Parcheado en 2.1.179 |
| Codex | Parcheado en 0.146.0 |
| Copilot | Reportado sin parche |
| Gemini CLI | Descontinuado; sin arreglo previsto, se redirige a los usuarios |
Cuatro equipos independientes, cuatro bases de código distintas y el mismo error en todas.
Esa última parte es la señal. Cuando cuatro competidores publican el mismo fallo, no son cuatro despistes. Es una suposición compartida que nadie llegó a escribir.
Los marketplaces de plugins fijan un plugin a un hash de commit concreto tras revisarlo. Este es el control en el que todo el mundo confía: fija un SHA y obtienes exactamente los bytes que alguien miró. Es el mismo instinto que hay detrás de un lockfile.
Esto es lo que hacían en realidad los agentes afectados:
Hasta aquí bien. Esta parte funciona.
También correcto, tomado por separado.
Nada te impide llamar a una rama a94a8fe5ccb19ba61c4c0873d391e987982fbbd3. No es más que una cadena de texto.
Porque nunca lo miró. Como lo formulan los investigadores: el agente hace checkout del commit exacto que fijó el marketplace, pero nunca verifica que haya aterrizado ahí.
La variante de Gemini CLI es otro camino al mismo sitio — una rama llamada FETCH_HEAD que desvía el checkout lejos del commit descargado — y ese detalle es lo que convierte esto en una clase de fallo y no en el desliz de un fabricante.
La lección generalizable
Una fijación no es integridad. Una fijación es una petición de integridad. La integridad viene del paso de verificación posterior — el que pregunta «¿de verdad he recibido lo que pedí?» — y ese es justo el paso que se omite, porque en la abrumadora mayoría de las ejecuciones la respuesta es sí y la comprobación parece código muerto. Cualquier punto de tu propio sistema donde obtengas algo por identificador y lo uses sin volver a derivar ese identificador de lo que llegó tiene esta misma forma.
Un fallo de cadena de suministro normalmente necesita que el usuario haga algo: instalar, actualizar, aprobar un aviso. Plugin4Shell no necesitaba nada de eso, y la razón es una función que le gusta a todo el mundo.
Claude Code y Codex ejecutan actualizaciones automáticas en segundo plano por defecto. Cuando un marketplace cambia un SHA fijado, el agente vuelve a ejecutar el checkout según su propio calendario. Si el atacante ya ha dejado preparada la rama maliciosa, el cambio ocurre en silencio, sin aviso, sin instalación y sin nadie delante.
Lo que invierte el consejo habitual:
Para dependencias normales, «activa las actualizaciones automáticas» es buena práctica de seguridad, porque casi todo lo que reparte la actualización automática son parches. Para una superficie de ejecución donde el propio camino de actualización es el componente vulnerable, actualizar automáticamente es el mecanismo de reparto. Los dos casos se ven idénticos en una página de políticas y se comportan en direcciones opuestas.
Es tentador leer «vulnerabilidad de plugin» como un problema contenido. No lo es, y esta es la parte que debería decidir cuán en serio se lo toma un equipo pequeño.
El código ejecutado a través del sistema de plugins de un agente de código obtiene, en la formulación de los investigadores, el mismo alcance sobre los sistemas y los datos de la empresa que el empleado que ejecuta el agente. En una máquina de desarrollo normal, eso significa:
El código fuente, incluidos los repositorios privados. Lectura de todo lo que esté clonado en local, y escritura en todo aquello a lo que el desarrollador pueda hacer push.
Sesiones de nube activas. Todo lo que ya esté autenticado en la terminal: credenciales de la CLI de la nube, kubeconfig, túneles a bases de datos. No hace falta robar credenciales; la sesión está abierta.
Archivos de entorno y almacenes de secretos. Los archivos .env, las entradas del llavero local, los tokens que siguen en un perfil de shell porque rotarlos daba pereza.
La propia superficie de herramientas del agente. Cada integración que el agente ya tiene permitida, ahora movida por el código de otra persona y con el historial de aprobaciones del usuario detrás.
Un puesto de desarrollo es la máquina menos segmentada de casi cualquier empresa y la que más alcance tiene. Eso está bien cuando el código que corre en ella es código que eligió una persona. Es otra cosa muy distinta cuando un camino de actualización puede cambiar lo que se ejecuta sin que nadie haya decidido cambiarlo.
Aquí está el punto estructural, y la razón por la que creo que esto importa más allá de un ciclo de parches.
Las dependencias de tu aplicación están gobernadas. Hay un lockfile, un escáner, un paso de revisión cuando alguien añade un paquete, y un SBOM si le vendes a alguien que lo pide. Esa maquinaria le costó veinte años al sector y en general funciona.
Los plugins, skills, extensiones e instalaciones de marketplace de tu agente no tienen nada de eso.
Las dependencias de aplicación suelen ejecutarse dentro de un servicio con una identidad acotada. Los plugins de agente se ejecutan en un puesto de trabajo con toda la autoridad de una persona. La capa con menos revisión tiene más alcance, que es exactamente al revés, y ocurrió por accidente: los plugins llegaron como una función de productividad, no como una cadena de suministro de software, así que nadie les enganchó la maquinaria de cadena de suministro.
La mayoría de los equipos con los que hablo no pueden responder a «qué plugins de agente hay instalados en el equipo, en qué versiones y de qué autores» sin ir mesa por mesa. Eso no es negligencia. Nadie les dijo nunca que fuera una pregunta.
Cuatro cosas, más o menos una tarde, y ninguna requiere un equipo de seguridad.
Claude Code 2.1.179 y Codex 0.146.0 o posteriores. Para todo lo reportado sin parche o descontinuado, la decisión es si conserva superficie de plugins siquiera: un camino de actualización sin arreglar no se monitoriza, se apaga.
Cada plugin, skill y extensión de agente instalados en el equipo, con autor y versión. Suele ser una lista corta y el ejercicio se acaba en una hora. Si resulta ser una lista larga, eso ya es el hallazgo.
Actualiza automáticamente el binario del agente: así es como recibes arreglos como estos. Plantéate poner una persona entre medias para las actualizaciones de plugins, al menos para los que pueden ejecutar código. Son dos decisiones distintas y hoy casi todos los equipos toman una sola por defecto para ambas.
Credenciales de nube de corta vida, ningún token de producción de larga duración en perfiles de shell, y ningún túnel a base de datos abierto todo el día. Este es el control que aguanta sea cual sea el agente que publique el próximo fallo, y por eso merece la pena hacerlo primero.
Y una cosa que añadir a tu propio código, sea lo que sea que construyas:
Busca cada punto donde obtienes algo por identificador — un commit, un digest, una versión de modelo, un identificador de documento — y comprueba si algo vuelve a derivar ese identificador a partir de lo que realmente llegó. Si la respuesta es «lo pedimos, así que será eso», tienes la forma de Plugin4Shell en tu propio sistema. Cerrarlo cuesta unas pocas líneas y es invisible hasta el día en que deja de serlo.
No se ha reportado explotación confirmada en el mundo real. Esto es una divulgación con exploits de prueba funcionales, no un informe de incidente. Las cifras que circulan sobre a cuántos agentes podría llegar un plugin malicioso son modelado de escenarios, no recuentos de instalaciones comprometidas, y las he dejado fuera a propósito.
El estado de los parches se movía durante la divulgación y las fuentes discrepan. Claude Code y Codex se reportan de forma consistente como arreglados en las versiones citadas. La cobertura sobre la exposición de Copilot no es consistente: unas versiones lo describen sin parche y otras como mitigado por controles de plataforma. Consulta el aviso de tu propio fabricante y no esta tabla.
Esto no es una vulnerabilidad de Git. Que Git resuelva una referencia ambigua en un orden documentado es Git funcionando según lo especificado. El fallo está en que los agentes supusieron que el resultado coincidía con la petición. Culpar a la herramienta sería la lección equivocada y te llevaría a no arreglar nada.
No he reproducido nada de esto. Todo el apartado 2 es mi lectura de descripciones publicadas del mecanismo, no una verificación independiente.
Lo interesante aquí no es que cuatro agentes de código tuvieran un fallo. Es qué suposición compartían: que nombrar algo con precisión es lo mismo que comprobar que lo has recibido.
Esa suposición está por todas partes. Está en cada integración que se fía de un webhook porque trae el identificador correcto, en cada caché que devuelve por clave sin validar el contenido, en cada pipeline que descarga latest y lo llama reproducible. Fijar un hash parecía seguro porque un hash es específico — pero la especificidad no es verificación, y el hueco entre ambas es exactamente donde vive esta clase de fallo.
Mientras tanto, la exposición práctica es poco lucida e inmediata: un camino de código capaz de cambiar lo que se ejecuta en la máquina de un desarrollador sin que nadie apruebe el cambio, en la máquina menos segmentada del edificio.
Actualiza los agentes hoy. Después dedica una hora a averiguar qué plugins tiene instalados tu equipo, porque ahora mismo esa es una pregunta que la mayoría de los equipos no sabe responder — y es la misma pregunta que te va a hacer la primera revisión de seguridad seria de un cliente.
Fuentes: The Register, «AI coding agents' 0-click RCE flaw could hand attackers keys to the kingdom», 17 de septiembre de 2026 — la cronología de la divulgación, las dos vías de ataque y las posiciones de los fabricantes. Help Net Security, «Zero-click RCE vulnerability hit four major AI coding agents», 18 de septiembre de 2026 — el descubrimiento en mayo de 2026, la comunicación en junio, las versiones parcheadas 2.1.179 y 0.146.0, y la formulación de los privilegios que hereda el código ejecutado. Cyber Security News — el mecanismo de la rama de 40 caracteres y la variante FETCH_HEAD que afecta a Gemini CLI. La investigación es de AIR. La generalización del apartado 2, el argumento sobre la actualización automática del apartado 3, el argumento del inventario del apartado 5 y todas las recomendaciones son míos. Para el incidente de cadena de suministro anterior en esta misma línea, véase la inundación de paquetes en RubyGems, y para el modelo de permisos que limita hasta dónde llega un plugin comprometido, véase los sistemas de permisos de agentes.
IdeaToMVP Academy
4-week live cohort for founders. Learn to ship AI agents, scope MVPs, and automate your business — taught by the same team that writes these guides.