El escáner dijo «seguro» y luego, con solo mirar la skill, se ejecutó


Instalas una skill de la comunidad desde un hub. Una línea installed pasa de largo, el informe del escáner dice que es segura y sigues con lo tuyo. Tres semanas después abres la skill en una sesión solo para mirarla, y algo se ejecuta.

El momento peligroso no fue instalarla. Fue mirarla. Aquí va qué escanea realmente el guardián de skills, tres casos que se le escaparon y la única acción de limpieza que merece la pena hacer hoy.

Cómo funciona el guardián

Las skills de origen externo pasan por un escaneo estático con regex y luego una política de instalación basada en confianza decide si se instalan:

Nivel de confianza veredicto safe veredicto caution veredicto dangerous
builtin (skills incluidas) permitir permitir permitir (nunca se escanean)
trusted (openai/skills, anthropics/skills, huggingface/skills, NVIDIA/skills) permitir permitir bloquear
community (cualquier otra fuente) permitir bloquear bloquear
agent-created permitir permitir error de vuelta al agente (solo cuando skills.guard_agent_created está activado)

Cada veredicto se cachea junto con una versión del escáner (SCANNER_VERSION, v6 antes de este arreglo). Esa versión importa: cuando cambia, los veredictos en caché dejan de valer y la skill se vuelve a escanear.

Los tres puntos ciegos

1. Solo un $HOME literal contaba como home

La regla que detecta «borra tu directorio home» coincidía con la cadena literal $HOME:

rm -rf $HOME/Documents     → coincidía, crítico
rm -rf ~/Documents         → no coincidía, juzgado seguro

Así que rm -rf ~/Documents pasaba de largo en todos los niveles de confianza. El arreglo también detecta las formas con tilde suelta (~/, ~ , ~*, ~$), tanto para rm como para rmdir.

2. Nadie vigilaba la sintaxis de auto-ejecución !`cmd`

Las skills de Hermes admiten un fragmento de shell inline: un !`cmd` escrito en el cuerpo de la skill se expande mediante bash -c cuando la skill se ve o se carga. Está desactivado por defecto y se configura explícitamente:

skills:
  inline_shell: false        # desactivado por defecto; actívalo solo para fuentes en las que confíes
  inline_shell_timeout: 10   # segundos por fragmento !`cmd`

Pero ninguna regla del escáner se correspondía con él. Una skill cuyo cuerpo contenía !`rm -rf ~/Documents` se escaneaba como segura, se instalaba y luego se ejecutaba la siguiente vez que la abrías.

El arreglo añade un patrón inline_shell_exec (severidad high, categoría execution). Exige un payload que no sea solo espacios, así que una skill que únicamente documenta la sintaxis no se marca.

3. Una instalación bloqueada se reportaba a sí misma como exitosa

El tercero no es una regla del escáner en absoluto: es la interfaz. La ruta de instalación del gateway del TUI ejecutaba do_install(skip_confirm=True) con una consola sink y devolvía installed: True incondicionalmente.

Así que cuando el escaneo de seguridad bloqueaba una skill, a quien llamaba (por ejemplo, una instalación con un clic en la app de escritorio) se le decía que la instalación había salido bien. Tras el arreglo, installed: True solo se devuelve de una instalación real; los fallos devuelven un sobre de error (código 5031) cuyo mensaje y data.log llevan la cola impresa —la explicación del bloqueo del escáner, la tabla de candidatos ambiguos o el fallo de fetch— en lugar de volcarla a un sink.

¿Se volverán a escanear las skills que ya tienes?

Sí, y funciona mediante el sello de versión, no reinstalando. Como las entradas de caché guardan scanner_version, en cuanto el escáner pasa a la v7:

  • los veredictos «safe» cacheados previamente se invalidan;
  • las skills de hub ya instaladas se vuelven a escanear con la v7 cuando se comprueban;
  • todo lo que se instale de nuevo pasa directamente por la v7.

El segundo punto es el que importa: si tu máquina sigue ejecutando el escáner v6, la conclusión «lo escaneé y era seguro» nunca fue válida para el caso de la tilde suelta: la regla simplemente no existía.

Qué hacer ahora

  1. Confirma la versión del escáner. Tras actualizar a un build con el arreglo, SCANNER_VERSION en tools/skills_guard.py debería mostrar skills-guard-v7 (antes era v6).
  2. Vuelve a escanear lo que ya instalaste. Esta es la importante:
    hermes skills audit
    Vuelve a escanear las skills de hub instaladas. La lista completa de subcomandos está en la referencia de hermes skills, y dónde encontrar skills se cubre en hubs de skills y fuentes de búsqueda.
  3. Deja skills.inline_shell desactivado salvo que confíes en la fuente. El flag está documentado como un opt-in explícito para fuentes de confianza; este arreglo deliberadamente no lo acotó por confianza (esa es una decisión de producto), así que la regla solo hace visible el riesgo en el momento de instalar.
  4. Conoce los límites del escáner. Es una regex, no un análisis de flujo de datos. Las propias notas de su módulo señalan un hueco conocido: las APIs de escritura a nivel de lenguaje —open(..., 'w'), Path.write_text, shutil.copy*— dirigidas a archivos de configuración del agente solo producen un hallazgo de referencia de baja severidad, porque una regex estática no puede vincular la llamada a un destino calculado dinámicamente. Pasar el escaneo no es lo mismo que ser seguro para ejecutar a ciegas.
  5. Revisa también las skills creadas por el agente. Con skills.guard_agent_created activado, un veredicto dangerous sobre una skill escrita por el agente se le devuelve al agente como error para que la reescriba; eso atrapa patrones malos evidentes, no es una revisión.

Para apretar aún más la frontera, skills locales del proyecto y el control de confianza cubre cómo entran las skills incluidas en el repo en la decisión de confianza, mientras que las skills opcionales y usar el catálogo de MCP con seguridad son otras dos caras de la misma pregunta.

En qué punto está esto

El PR #128443 se fusionó en main el 2026-09-30; hay un informe anterior de la misma familia de problemas (issue #63307, el veredicto del escaneo tragado en el RPC de instalación). El tag más reciente, v0.21.5, es del 9-24, así que los tags todavía distribuyen el escáner v6: las instalaciones por git que siguen main ya están en la v7.

La conclusión

Los tres puntos ciegos comparten una misma forma: el escáner mira qué caracteres están escritos, mientras que el riesgo real suele vivir en cómo se ejecutan esos caracteres. $HOME y ~ son el mismo directorio; !`...` y bash -c ... son la misma ejecución. La coincidencia estática ve lo primero y se pierde lo segundo.

La acción más valiosa para ti es corta: después de actualizar, ejecuta hermes skills audit. Vuelve a comprobar las skills que ya están en tu máquina con la v7, y algunas de ellas nunca se habían comprobado de verdad.