El guardia y el shell no coincidían
El 30 de junio, Adversa AI reveló GuardFall — una clase de evasiones que hace pasar trucos de bash con décadas de antigüedad directamente ante los guardias de comandos integrados en 10 de los 11 agentes de código open source más populares. La razón es simple e imposible de corregir en esa capa: el guardia lee el texto, y bash reescribe el texto antes de ejecutarlo. Bromure Agentic Coding nunca apostó a que el guardia leyera bash correctamente. Apostó a que el comando no importa en el momento en que se ejecuta.
El filtro de seguridad de un agente de código miró la cadena
r''m -rf ~ y vio un comando que no reconoció, así que lo dejó pasar.
Bash miró la misma cadena, descartó las comillas vacías y ejecutó
rm -rf ~. El filtro y el shell estaban leyendo dos lenguajes distintos.
Esa brecha no es un fallo de una herramienta — es la idea entera de
proteger un agente comparando por patrones los comandos que teclea, y
Adversa AI acaba de mostrar que falla en diez de los once agentes que
probaron.
El guardia de comandos es la característica a la que toda herramienta de
código agéntico recurre primero. El agente propone un comando de shell; un
filtro inspecciona la cadena; si parece destructiva — rm -rf, un
curl … | sh por tubería, un dd a un dispositivo en bruto — el guardia
la bloquea o te pide que confirmes. Es lo que te deja activar la ejecución
automática y sentirte a salvo. El 30 de junio de 2026, Adversa
AI
publicó una investigación, recogida por The Hacker
News
y SecurityWeek,
mostrando que la característica es teatro.
Qué es GuardFall
Lo llaman GuardFall, y no es un CVE. No hay nada que parchear, porque no es un fallo en un componente — es un desajuste entre dos de ellos. En palabras de Adversa: «Un guardia inspecciona texto en bruto, mientras que el shell del sistema (bash) expande, desentrecomilla y reescribe el texto antes de ejecutarlo.» El filtro coincide con la cadena que emitió el modelo. Bash pasa entonces esa cadena por la eliminación de comillas, la expansión de variables y la sustitución de comandos antes de que se ejecute un solo byte. Los dos nunca miran el mismo comando, así que cualquier truco que sobreviva a la reescritura pero no a la coincidencia navega sin problemas.
Estos trucos son más viejos que la mayoría de la gente que usa los agentes. Adversa los agrupó en cinco clases:
- Eliminación de comillas.
r''mson dos tokens para una regex y la palabrarmpara bash, que descarta las comillas vacías. - Expansión de variables.
rm$IFS-rf$IFS/parece una sola palabra larga para un comparador de patrones; bash expande el Separador de Campo Interno y obtienerm -rf /. - Sustitución de comandos.
$(echo rm) -rf /esconde el verbo peligroso dentro de$( ); el guardia que inspecciona la cadena externa nunca verm. - Tuberías codificadas.
echo <base64> | base64 -d | sh— cada token visible es inofensivo; la carga solo existe tras decodificar. - Flags destructivas alternativas. Ningún
rm:find /x -delete,tar -C / -x,sed -i. Una lista negra construida en torno armyddnunca se dispara.
Adversa lanzó estos trucos contra once de los agentes de código y de uso de
ordenador open source más usados — opencode, Goose, Cline, Roo-Code, Aider,
Plandex, Open Interpreter, OpenHands, SWE-agent y el proyecto Hermes entre
ellos, que suman unas 548.000 estrellas de
GitHub
entre todos hasta mayo. Diez cayeron. El único que aguantó, Continue,
aguantó por una razón concreta: en lugar de comparar la cadena en bruto,
tokeniza el comando como lo hará bash antes de decidir — absorbiendo las
comillas, resolviendo $IFS, extrayendo el comando interno de una
sustitución, marcando cualquier tubería que termine en sh. Modela el
shell. Es lo único que funciona en la capa del guardia, y es ingeniería
real y cuidadosa que los otros diez tendrán ahora que reproducir,
correctamente, y mantener correcta con cada caso límite de bash y cada
versión.
El problema es la capa, no la regex
La tentación es leer GuardFall como «diez equipos escribieron filtros débiles». Eso pasa por alto lo que dice Adversa. Su frase más afilada no es sobre ningún agente en particular:
Un agente que puede ejecutar comandos de shell arbitrarios en el host del operador, controlado por una regex que compara la cadena emitida por el LLM, no es una defensa. Falla mientras está plenamente habilitado y correctamente configurado, porque la comparación de cadenas no puede modelar lo que bash va a ejecutar.
Plenamente habilitado y correctamente configurado. Esto no es una mala configuración que puedas cerrar. El guardia se sitúa en la única capa donde nunca puede ganar — entre un modelo que escribe cadenas y un shell que las reinterpreta — y le pide a un comparador de texto que prediga la salida de un expansor Turing-completo. El enfoque tokeniza-y-canoniza de Continue estrecha la brecha enseñando al guardia a pensar como bash, y es el movimiento correcto si vas a mantener un guardia ahí. Pero es un compromiso por agente y por versión de superar en análisis a un shell que ha pasado treinta años acumulando maneras de reescribir un comando. Otros nueve agentes populares muestran lo fácil que es equivocarse.
Los controles compensatorios de Adversa son reveladores. Antes de cualquier
solución estructural, te dicen que redirijas $HOME a un sandbox acotado
que conserve el acceso al proyecto pero elimine las credenciales, que
retires las flags de ejecución automática, que impidas que los agentes
corran sobre pull requests no confiables, y que trates todo archivo de
configuración de repositorio como código no confiable. Relee esa lista. No
es consejo sobre cómo escribir un mejor filtro. Es consejo sobre cómo
construir una caja alrededor del agente para que, cuando el filtro pierda —
y te están diciendo que perderá — el comando que pase aterrice en algún
lugar donde no pueda hacerte daño.
Esa caja es el producto.
Bromure nunca le pidió al guardia que leyera bash
Bromure Agentic Coding parte del supuesto que GuardFall demuestra: el
agente, tarde o temprano, ejecutará un comando que no sancionaste. No
intenta atrapar ese comando leyéndolo. Ejecuta el agente entero — Aider,
Goose, opencode, el que quieras de los diez — dentro de una VM de Linux
desechable, y enruta cada petición de red a través de un proxy en el host.
La pregunta de diseño nunca es «¿reconocerá el filtro este rm?». Es
«cuando el rm se ejecute, ¿qué alcanza?».
Haz pasar las propias cargas de GuardFall por esa caja.
El objetivo del ataque, una vez que un r''m oculto o un
find /x -delete cuela un README con trampa ante el guardia, es robar lo
que la cuenta puede alcanzar — Adversa nombra ~/.ssh, ~/.aws,
credenciales de nube, «cualquier cosa que esté en tu carpeta personal» — y
borrarlo o exfiltrarlo. En Bromure, esas son las cosas que nunca estuvieron
en la caja. Los secretos reales nunca entran en la VM: cuando le das a un
perfil una AWS_SECRET_ACCESS_KEY, un token de GitHub, una clave de
Anthropic, el entorno del agente recibe un marcador brm_…, y el proxy del
host intercambia el falso por el valor real sobre el cable, solo en la
petición saliente al proveedor que debe recibirlo. La mitigación
recomendada por Adversa — mover $HOME a algún lugar que «conserve el
acceso al proyecto pero elimine las credenciales» — es una versión
artesanal y parcial de lo que un perfil Bromure hace por defecto, para cada
credencial, sin que tú lo programes.
La mitad destructiva aterriza igual. Un find /x -delete o un sed -i que
se cuela ante el guardia sí se ejecuta — Bromure no pretende haber atrapado
el comando. Se ejecuta contra un directorio personal clonado desde una base
compartida, en una VM que puedes borrar y restablecer a la base desde un
menú, no un formulario de incidente. La persistencia que una carga pudiera
dejar muere en ese restablecimiento. Y como cada petición sale por el proxy
del host, la baliza curl … | base64 -d que la clase de tuberías
codificadas de GuardFall está hecha para ocultar no es invisible: es una
línea registrada y atribuible en el Registro de Seguridad.
El único lugar donde el cable vence al shell
Bromure sí mantiene un guardia de operaciones destructivas — sus Guardrails del lado del host, sobre los que escribimos después de que un agente de Cursor borrara una base de datos de producción en nueve segundos. Y aquí la capa juega a favor de Bromure, porque los Guardrails no viven donde vive GuardFall.
GuardFall es un ataque de texto de shell. Cada una de sus cinco clases —
eliminación de comillas, $IFS, $( ), tuberías base64, flags exóticas —
es un truco de cómo bash lexica una cadena. Los Guardrails de Bromure nunca
leen esa cadena. Se sitúan en el proxy del host y clasifican la llamada de
API estructurada que el agente hace a un proveedor que entiende — la
petición HTTPS real a AWS, Kubernetes, una forja git, una base de datos
gestionada — y devuelven un 403 firme en las destructivas, sobre el
cable, donde un agente comprometido en la VM no puede apagarlas. Para
cuando una petición alcanza esa capa ya es un DeleteDBInstance analizado,
no una cadena de comillas y signos de dólar. No hay reescritura de shell
para colar nada, porque no hay shell en el camino. La técnica entera de
GuardFall necesita un bash entre la comprobación y la acción; en el camino
de los Guardrails, no lo hay.
Qué acota esto, para que quede claro
El comando igual se ejecuta
Bromure es aislamiento, no intercepción. Una carga GuardFall que se cuela ante el propio guardia de tu agente se ejecutará dentro de la VM. Lo que Bromure cambia es el radio de daño: un home desechable, credenciales señuelo, una ruta de salida registrada. Si necesitas que el comando en sí sea rechazado, ese es trabajo del guardia de tu agente — y GuardFall es la razón por la que no deberías apoyarte en él.
La destrucción local es descartabilidad, no un bloqueo
Un find /x -delete contra archivos dentro de la VM no es una llamada de
API de proveedor, así que los Guardrails no lo controlan. La respuesta a
la destrucción dentro de la VM es que la VM es desechable y el trabajo
real vive en un repo montado y en el host, no que el borrado se detuvo.
Restablecer a la base, no revertir.
La sustitución cubre las credenciales que configuras
El intercambio brm_… protege los secretos que pones en un perfil —
claves de modelo, tokens de nube y git, endpoints de bases de datos
gestionadas. Una contraseña que pegas a mano en un archivo dentro de la
caja, o un token que un script escribe en disco a mitad de sesión, es
solo un archivo. Guarda los secretos en el broker, no en el espacio de
trabajo.
La salida se registra, no se prohíbe por defecto
La baliza de exfiltración aparece en el Registro de Seguridad; eso es atribución, no prevención. Nada real sale porque las credenciales son señuelos, pero si necesitas que la VM tenga vetado hablar con hosts arbitrarios, esa es una política de red que aún debes fijar.
La parte que se generaliza
GuardFall es un enunciado limpio de una regla que la categoría entera no para de reaprender: no puedes hacer seguro un agente pidiéndole a un filtro que prediga lo que su comando hará. El modelo escribe una cadena, y en algún lugar por debajo un shell, un cliente de API, un gestor de paquetes o un navegador reinterpreta esa cadena con sus propias reglas. Toda defensa que inspecciona la salida del agente y espera que coincida con el comportamiento final está apostando contra esa brecha, y la brecha siempre gana — ganó aquí en diez de los once agentes que estaban, en palabras de Adversa, plenamente habilitados y correctamente configurados.
Bromure Agentic Coding no hace esa apuesta. Asume que el comando se ejecutará, que el guardia a veces fallará, y que el agente que invitaste puede ser vuelto contra ti por un README que nunca escribiste. Así que hace que el lugar donde el comando se ejecuta no valga la pena atacar: claves reales en el host, señuelos en la caja, una VM desechable, un bloqueo firme reservado al cable donde ningún shell puede reescribirlo, y un registro de todo lo que intentó salir. Puedes ejecutar cualquiera de los diez agentes que GuardFall rompió — el resultado es la misma caja desechable de todos modos. Es libre y de código abierto.