
Implementación de soporte completo para anclajes YAML en zizmor
FUENTE
The Trail of Bits Blog
DATE
READ
6 min de lectura
En marzo de 2026, un incidente de seguridad relacionado con la acción de GitHub aquasecurity/trivy-action reveló vulnerabilidades en la configuración de GitHub Actions. Para abordar posibles configuraciones incorrectas, …
En marzo de 2026, los atacantes explotaron una configuración incorrecta de pull_request_target en la acción de GitHub aquasecurity/trivy-action para exfiltrar secretos de la organización y el repositorio, y luego utilizaron esas credenciales para “backdoor” a LiteLLM en PyPI (ver el post-mortem de Trivy para el cronograma completo). zizmor es un analizador estático que los usuarios de GitHub Actions ejecutan para detectar exactamente estas configuraciones incorrectas antes de implementarlas. Cuando GitHub Actions agregó soporte para anclajes YAML en septiembre de 2025, una pequeña pero valiosa porción del ecosistema comenzó a escribir flujos de trabajo que zizmor solo podía analizar de manera “best-effort”. Durante los últimos tres meses, Trail of Bits colaboró con los mantenedores de zizmor para llevar el soporte de anclajes de zizmor a una cobertura completa. Primero, solucionamos errores de análisis que causaban fallas, generaban resultados incorrectos y manejaban de forma silenciosa valores anidados. En segundo lugar, hicimos visibles los casos límite de deserialización que rompían zizmor en flujos de trabajo válidos. Finalmente, ayudamos a alinear el evaluador de expresiones de zizmor con las Pruebas de Respuestas Conocidas de GitHub. Validamos todo esto contra un nuevo corpus de 41.253 flujos de trabajo de 6.612 repositorios de código abierto de alto valor. El resultado: 20 problemas reportados, 15 solicitudes de extracción fusionadas. Construir el corpus de prueba Para entender cómo se utilizan los anclajes en CI hoy y para poner a prueba a zizmor contra la variedad completa de YAML que encuentra en el mundo real, construimos un corpus de flujos de trabajo reales. Utilizamos BigQuery’s GitHub dataset para identificar los 10.000 repositorios más estelarados creados entre 2022 y 2025, filtrados para los 6.612 que utilizan GitHub Actions, y descargamos todos los archivos de flujo de trabajo. Esto nos dio 41.253 archivos YAML. Figura 1: Construir un corpus de prueba Cuando ejecutamos zizmor contra el corpus, falló en 45 de los 41.253 flujos de trabajo. Esto es una tasa baja, pero cada fallo significa un fallo en zizmor. Cómo se utilizan los anclajes en el mundo real El soporte de anclajes de zizmor se limitó intencionalmente, y por una buena razón. Los anclajes YAML hacen que los flujos de trabajo sean no locales: un alias definido en un lugar cambia el comportamiento en otro lugar del archivo. Esto complicó el modelo de análisis de zizmor, y la adopción fue lo suficientemente rara como para que los mantenedores de zizmor razonablemente desalienten el uso de anclajes. En nuestro corpus, solo 43 de los 41.253 flujos de trabajo utilizan anclajes YAML (aproximadamente 0,1%), pero esos 43 incluyen algunos de los proyectos fundamentales más importantes en el código abierto: Bitcoin Core PHP OpenSSL Sin embargo, los anclajes son una función soportada, y es probable que su uso crezca con el tiempo. Encontramos dos patrones comunes. El primero es reutilizar pasos en trabajos, como lo hace el CI de Bitcoin Core: jobs: runners: steps: - &ANNOTATION_PR_NUMBER name: Annotate with pull request number run: | if [ ${{ github.event_name }} = pull_request ]; then echo ::notice … fi test-each-commit: steps: - *ANNOTATION_PR_NUMBER - uses: actions/checkout@v6 Figura 2: Reutilizar la definición de paso El segundo patrón es fijar versiones de acción una vez. Por ejemplo, el CI de Home Assistant define la referencia de la acción (con su SHA hash) utilizando un anclaje, y luego la reutiliza donde aparece la misma acción: jobs: lint: steps: - uses: &actions-setup-python actions/setup-python@a309ff8b42… # más tarde en el mismo flujo de trabajo: - uses: *actions-setup-python Figura 3: Reutilizar la definición de acción Cuatro errores de manejo de anclajes encontrados y corregidos Cuando empezamos, cuatro patrones de anclajes de estos flujos de trabajo rompieron zizmor. Los alias en secuencias se “aplanaron” incorrectamente. Cuando un alias YAML aparecía dentro de una secuencia (como una lista de pasos), la representación de ruta interna de zizmor extendía el contenido del alias en lugar de tratarlo como un solo elemento. Esto provocaba que zizmor fallara o generara resultados incorrectos en el archivo. (Solucionado en #1557) Los prefijos de anclaje se filtraban en valores. foo: [&name v, *x] Figura 4: Fuga de prefijo de anclaje En secuencias de flujo YAML, los prefijos de anclaje como &name no se eliminaban de los valores resueltos. Dado el fragmento en la Figura 4, buscar el primer elemento de foo devolvería &name v en lugar de v, lo que haría que cualquier paso que consumiera el valor del nodo fallara. (Solucionado en #1562) Los anclajes duplicados provocaron un fallo. La especificación YAML permite redefinir un nombre de anclaje (la última definición gana). La capa YAML de zizmor asumió que los nombres de los anclajes eran únicos y se bloqueó con duplicados. (Solucionado en #1575) La auditoría de inyección de plantillas falló en valores anidados. Cuando se usaba un alias YAML como un valor escalar: run: la auditoría no esperaba la indización y falló. (Solucionado en #1732) Para evitar futuras regresiones, también agregamos pruebas de integración que cubren patrones de anclaje que se encuentran en flujos de trabajo reales (#1682) y actualizamos la documentación de anclajes (#1788). Otras cosas que reveló el corpus Ejecutar zizmor contra el corpus completo también reveló errores que no tenían nada que ver con los anclajes. Casos límite de deserialización. GitHub Actions acepta construcciones YAML que no anticipa el modelo de flujo de trabajo de zizmor: if: 0 (un entero donde se espera una cadena), timeout-minutes: 0,5 (una coma flotante donde se espera un entero), secrets: inherit (una cadena donde se espera un mapa). Cada uno hizo que zizmor rechazara todo el flujo de trabajo. Los reportamos como problemas individuales (#1670, #1672, #1674), y los mantenedores los solucionaron rápidamente. Errores de evaluador de expresiones. Zizmor evalúa expresiones de GitHub Actions para determinar si los datos de control del usuario fluyen a los puntos de inyección. Validamos el evaluador contra las Pruebas de Respuesta Conocidas de GitHub y ayudamos a los mantenedores a alinear el comportamiento de zizmor con el conjunto de pruebas oficial (#1694). Problemas de nivel superior También rastreamos algunos fallos a dependencias de nivel superior, tree-sitter-yaml, y reportamos problemas y PRs allí (tree-sitter-yaml#39, tree-sitter-yaml#43). Incluso el conjunto de pruebas YAML 1.2 no cubre todos los casos límite que permite la especificación. Segurando CI donde más importa Los ataques de la cadena de suministro, como el compromiso de Trivy, comienzan con una configuración incorrecta. GitHub Actions es el sistema de CI más popular para proyectos de código abierto, y zizmor juega un papel importante para ayudar a los mantenedores a detectar configuraciones riesgosas antes de que lo hagan los atacantes. Al recopilar 41.253 flujos de trabajo reales y ejecutando zizmor contra todos ellos, probamos su robustez contra la variedad completa de patrones YAML que realmente usan los proyectos. Solucionamos varios errores de manejo de anclajes, informamos problemas de deserialización y evaluador de expresiones, y ampliamos el conjunto de flujos de trabajo que zizmor puede analizar limpiamente. La metodología es sencilla: descargar entradas reales, ejecutar la herramienta, hacer triage de los fallos. Cualquier herramienta de análisis estático puede beneficiarse del mismo enfoque. Nos gustaría agradecer a los mantenedores de zizmor, en particular Woodruff, por su capacidad de respuesta y revisión de código exhaustiva durante todo este trabajo. También nos gustaría agradecer a la Sovereign Tech Agency, cuyo enfoque para la seguridad de OSS y financiación hizo posible este trabajo.