Miri, target/ y GitHub Actions: cómo cerrar una fuga de secretos en CI
La alerta de Rust muestra cómo Miri, una caché de target/ y secretos en un job pueden exponer datos a pull requests. Este checklist ayuda a revisar y contener el riesgo.
22 de septiembre de 2026 · Leopoldo Benavente Cadena · 5 min de lectura
La alerta de Rust del 21 de septiembre describe una fuga posible entre el entorno de un job y sus artefactos. Miri es el intérprete de MIR (la representación intermedia de Rust) que ejecuta binarios y pruebas para detectar comportamiento indefinido; en el comportamiento afectado guardaba variables de entorno en target/. Si un workflow almacenaba esa carpeta en una caché de GitHub Actions y el job recibía secretos, un pull request con acceso a la caché podía encontrar esos valores.
La precisión importa. Rust no afirma que Miri sea malicioso, que todas las cachés sean públicas ni que todos los proyectos estén afectados. El riesgo aparece cuando coinciden cuatro condiciones: cargo miri en CI, secretos visibles para el proceso, target/ persistido y una política que permite a pull requests leer la caché. Ejecutar Miri localmente, sin persistir sus archivos, no satisface esa combinación.
Qué está confirmado
La alerta oficial de Rust dice que el comportamiento vigente de Miri necesitaba conservar variables relevantes entre ejecuciones y las escribía en target/. El mismo aviso menciona un repositorio identificado con el problema y otros siete que debían actuar con cautela; también reconoce que el escaneo podía ser imperfecto. Es una señal para auditar, no una lista completa de repositorios comprometidos.
La corrección está documentada en el PR #5337 de Miri, titulado “only preserve env vars cargo actually changes”, que aparece integrado el 21 de septiembre. El código corregido conserva OUT_DIR y las variables cuyo nombre empieza por CARGO_, salvo las que terminan en _TOKEN. El manifiesto de la nightly 2026-09-22 ya incluye miri-preview con el commit de toolchain correspondiente. Eso no demuestra que todos los runners o imágenes de CI la estén usando: comprueba el toolchain real del workflow y fíjalo de forma reproducible.
GitHub advierte en su documentación de cachés que no deben guardarse tokens, credenciales ni datos sensibles. Una caché se restaura tal cual y puede leerla una ejecución con acceso, según el alcance del repositorio y la rama. La referencia explica que la búsqueda puede continuar hacia la rama predeterminada y que restore-keys amplias aumentan coincidencias. El nombre de la rama no sustituye a revisar la configuración.
Auditoría de cinco minutos
Empieza por el YAML de workflows y busca en cada job, no solo en el archivo completo:
rg -n "cargo miri|miri|actions/cache|swatinem/rust-cache|target/|restore-keys|secrets\." .githubDespués responde estas preguntas:
- ¿El mismo job que ejecuta Miri recibe secretos mediante
env,with, un entorno protegido o una variable exportada antes del paso? Un secreto usado en otro job no pertenece automáticamente al alcance de Miri, pero comprueba dependencias y artefactos entre jobs. - ¿La caché incluye
target/completa o una ruta que pueda contener la salida de Miri? Revisa tantopathcomo las rutas construidas por acciones de terceros. - ¿El workflow se activa con
pull_requesty acepta forks? Un pull request desde un fork normalmente no recibe los secretos del repositorio en ese evento, pero puede leer o restaurar una caché previamente escrita por una ejecución con secretos, según el evento, el alcance, las claves y los permisos concretos. Comprueba qué permisos tiene el workflow y qué modo de caché usa el repositorio. Revisa tambiénpull_request_targetyworkflow_run: combinarlos con código no confiable requiere una separación deliberada de privilegios. - ¿Existen
restore-keysgenéricas que permitan recuperar una caché producida por otra ejecución? Documenta la clave, la rama, el evento y quién puede leerla. - ¿La toolchain está fijada y la nightly contiene la corrección? Guarda la versión usada en los logs para poder reconstruir qué ejecuciones pudieron escribir archivos.
El objetivo no es afirmar una descarga sin evidencia, sino determinar si los secretos pudieron entrar en la caché y si un pull request tenía una ruta legítima para leerla.
Contención si la combinación existe
Primero corta la persistencia: desactiva la caché del job de Miri o excluye target/ mientras investigas. Ejecuta Miri en un job sin secretos; pasa credenciales solo al paso que las necesita y nunca a un proceso cuyos resultados vayan a una caché. Pausar Miri es preferible a mantener abierta la exposición.
Antes de limpiar, conserva workflow, claves de caché, logs, historial de ejecuciones y permisos. Después elimina las cachés potencialmente expuestas y rota los secretos disponibles para el job. La rotación invalida credenciales, pero no dice quién pudo leerlas ni qué artefactos se generaron; revisa los logs.
Audita también tokens de publicación, credenciales de nube, claves de firma y variables que llegan desde entornos protegidos. Si una caché se restauró en una ejecución de confianza, trátala como entrada no confiable: GitHub advierte que una caché envenenada puede influir en comandos o código que se ejecuten después. No borres evidencia de forma indiscriminada ni marques el repositorio como comprometido sin confirmar el alcance.
Corrección y límites
La nightly 2026-09-22 ya contiene la corrección y ofrece miri-preview con el filtro descrito. Fija y registra el toolchain efectivo del runner y comprueba que tu workflow instaló esa nightly; una imagen o una actualización automática no implica que todos los proyectos la hayan recibido. Después prueba dos casos: una ejecución normal de Miri y otra con la caché habilitada, inspeccionando qué archivos se escriben. Vuelve a evaluar la clave y el alcance de lectura antes de reactivar el almacenamiento.
El parche reduce el conjunto de variables que Miri conserva; no es una licencia para cachear secretos. Un build.rs, una herramienta de análisis o una acción de terceros puede escribir el entorno en un archivo distinto. Por eso la regla de diseño debe ser más amplia: separa la compilación que necesita credenciales de la generación de artefactos reutilizables, usa permisos mínimos y evita que target/ cruce una frontera de confianza sin una revisión explícita.
La mitigación duradera es que un pull request no confiable pueda compilar y probar sin heredar secretos ni escribir en una caché compartida. Reserva los jobs con credenciales para ramas y entornos controlados, limita sus rutas de salida y prefiere cachés estrechas, con claves previsibles y sin restore-keys que oculten el origen. Esa arquitectura sigue siendo válida aunque Miri ya no persista el entorno.
Fuentes primarias
- Rust Security Response Team: GitHub Actions leaking secrets when Miri output is cached.
- rust-lang/miri, PR #5337.
- Código corregido de
cargo-miri(util.rs). - Manifiesto oficial de Rust nightly 2026-09-22.
- README oficial de Miri.
- GitHub Docs: Dependency caching.
- GitHub Docs: Dependency caching reference.
Comentarios