El instrumento que se acusó a sí mismo: 28 hallazgos, 1 CRÍTICO y un mecanismo que no lo sostiene
Un clasificador automático marcó un hallazgo CRÍTICO en google/gvisor. Después de leer el mecanismo que lo sostiene, el hallazgo se degradó a sí mismo. Esta es la auditoría donde el instrumento tuvo que acusarse a sí mi
Un clasificador automático marcó un hallazgo CRÍTICO en google/gvisor. Después de leer el mecanismo que lo sostiene, el hallazgo se degradó a sí mismo.
Esta es la auditoría donde el instrumento tuvo que acusarse a sí mismo, y el resultado es más útil que el hallazgo original.
El sujeto y su referencia
google/gvisor @ 2f5253abfaa87b6d62d79a0da60942e773389934 — 15 archivos .github/workflows/*.yml, leídos como texto, sin clonar y sin parser YAML.
Un conteo sin su ref es otro objeto. El registro de la corrida anterior, contra 6ff6a1f498df, devolvió 31 hallazgos. Esos dos ref están a 8 commits de distancia (ahead=0, behind=8), y en el camino los hallazgos pasaron de 31 a 28. Se publica el del informe y se declara el del registro; no se elige el número que suena mejor.
El hallazgo, y por qué no se sostiene
En .github/workflows/go.yml (job generate), 4 de las 5 apariciones de ${{ secrets.* }} caen dentro de bloques run:.
GitHub expande esas expresiones en el texto del script antes de que el shell lo lea. Así que el valor del secreto se parsea como sintaxis. Medido, con un valor sintético:
- un valor con una comilla doble rompe el
[[ ]]→bashrc 2, el paso muere; - un valor con
$(...)se ejecuta → rc 0.
Lo que hace que esto no sea una exposición crítica no es una opinión, es una propiedad del disparador: el que dispara es el valor del secreto, no una entrada del atacante. Ninguna entrada controlable por quien abre un pull request llega a esa expansión, y GitHub enmascara el valor en el log. El fallo se convierte en caída o en ejecución local — no en fuga hacia un tercero.
Por eso la severidad efectiva es higiene latente, no exposición crítica. El remedio es de una línea y también está medido: pasar el secreto por env:, donde el mismo valor con comilla queda inerte.
El clasificador no se equivocó al mirar. Se equivocó al concluir sin mirar el disparador. Y el instrumento que publica el veredicto tiene que ser capaz de decir eso de sí mismo.
El conteo independiente
Reproducido con curl, sin clonar, sin token y sin dependencias:
- 15 workflows leídos.
-
12 sin
permissions:raíz. -
1 workflow con secreto dentro de
run:— 4 ocurrencias; 7 quedan fuera derun:. -
23/23
uses:fijados (ninguno flotante). -
0
continue-on-error.
Los 12 sin permissions: raíz se publican como indeterminados, no como expuestos: quien decide si heredan read o write es el permiso por defecto de la organización, y este instrumento no lo lee.
El límite, dentro del artefacto
El instrumento juzga el YAML como texto y no publica número de línea. No observó runtime ni leyó el historial de Actions, así que no afirma que ningún flujo concreto se haya disparado. Fuera de alcance declarado: workflows reutilizables (workflow_call), acciones compuestas alojadas en repositorios ajenos, y el interior de los scripts del árbol.
El conteo se reproduce con un script; la severidad no, porque es un juicio. Por eso se publica con su mecanismo al lado en vez de sola.
Reproducirlo
python3 reproduce.py # RC 0 — 6 de 6 afirmaciones reproducen, sin red
python3 reproduce.py --control # control negativo: las dos cifras tienen que moverse
python3 reproduce.py --remoto # testigo: compara objeto/ con el commit fijado
La copia fijada en objeto/ (15 archivos, byte a byte, Apache-2.0) es el sujeto del veredicto. --remoto sólo la testifica y no la sustituye: un testigo divergente no cambia el resultado.
El caso completo, con la ficha, el contador y el control negativo: https://alexisromtz-lab.github.io/la-auditora/portafolio/auditoria-003-gvisor/
Regla de esta serie: un hallazgo que no demuele nada suyo no se publica. Este publica su propia degradación.
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.