ataques a la cadena de suministro , GitHub Actions ha sido objeto de numerosos ataques a la cadena de suministro , y las configuraciones erróneas de los flujos de trabajo han desempeñado un papel fundamental. ¡Es peligroso ir por libre! Echa un vistazo a esta lista de comprobación.

¿Por qué hay tantos problemas de seguridad con GitHub Actions?
GitHub Actions, el sistema integrado de CI/CD y automatización de GitHub, no presenta por sí mismo vulnerabilidades de seguridad, pero sí que ofrece muchas formas de meterse en líos.
La plataforma funciona según lo previsto, pero los ajustes predeterminados suelen estar configurados pensando en la comodidad y la flexibilidad, no en la seguridad. pull_request_target existe por una razón, y las etiquetas modificables son sin duda muy prácticas. Pero esas decisiones de diseño crearon una superficie de ataque que no se hizo evidente hasta más tarde.
GitHub Actions es también el sistema de CI/CD predeterminado para la mayoría de los proyectos de código abierto, y el secuestro de un proyecto de código abierto permite a los hackers acceder a las víctimas más lejanas de la cadena. Los flujos de trabajo suelen contener credenciales para publicar en npm y PyPI, por lo que un flujo de trabajo comprometido puede publicar una versión maliciosa de un paquete, y todos los desarrolladores que instalen ese paquete también la recibirán.
Otra razón más por la que seguimos viendo aparecer tantos vectores similares en los incidentes es que la superficie de ataque lleva años estando bien documentada en investigaciones públicas. A veces, los atacantes se limitan a escanear los repositorios en busca de estas configuraciones erróneas para encontrar objetivos fáciles de atacar (véase prt-scan). GitHub va a dar prioridad a la implementación de medidas de protección más sólidas durante el próximo año para proteger mejor a los usuarios, pero sigue recayendo en el usuario gran parte de la responsabilidad de configurar GitHub de forma segura y correcta.
Seguir todas las buenas prácticas no hará que tus flujos de trabajo sean a prueba de fallos. Aunque no puedes protegerte por completo frente a un mantenedor malintencionado o una vulnerabilidad de día cero en la infraestructura de GitHub, sí puedes cerrar muchos de los vectores que los atacantes están aprovechando activamente últimamente, lo que hará que tus repositorios sean un objetivo más difícil de lo habitual.
Buenas prácticas para mantener seguros tus flujos de trabajo de GitHub Actions
Empieza por aquí. Si solo haces cinco cosas de esta lista:
- Asignar todas las acciones de terceros a un SHA de confirmación completa
- Establecer como predeterminado
GITHUB_TOKENpermisos de solo lectura - Nunca
pull_request_targeten repositorios públicos - Nunca interpoles
${{ github.* }}directamente enejecutar:pasos - Utiliza OIDC para las credenciales en la nube en lugar de claves secretas de larga duración
No obstante, te recomendamos que leas detenidamente la lista de verificación, en la que explicamos todos nuestros consejos de seguridad para GitHub Actions y por qué son necesarios. Echa también un vistazo a las herramientas que aparecen al final, que te ayudarán a implementar y aplicar estas buenas prácticas.
Configuración de los disparadores
1. Nunca utilices `pull_request_target` en repositorios públicos
pull_request_target Su finalidad es permitir que los flujos de trabajo activados por solicitudes de incorporación de cambios (PR) de bifurcaciones se ejecuten con acceso a los secretos del repositorio base. Permite etiquetar o comentar automáticamente las PR de colaboradores externos. Es una buena idea, pero el acceso a los secretos la convierte en algo peligroso.
A diferencia del estándar solicitud de incorporación gatillo, pull_request_target se ejecuta en el contexto del repositorio base, independientemente del origen de la solicitud de incorporación de cambios. Cualquiera puede abrir una solicitud de incorporación de cambios en un repositorio público. Si tu flujo de trabajo se activa con esa solicitud, aunque no se haya fusionado, cualquier secreto al que se haga referencia explícita en el flujo de trabajo se carga en el entorno del ejecutor y queda accesible para cualquier código que se ejecute en dicho ejecutor. El script del atacante puede leer fácilmente cualquiera de ellos mediante una consulta al entorno como os.environ.get('MY_SECRET') y reenviárselas al atacante sin dejar rastro.
Si lo necesitas en un repositorio privado, exige a los colaboradores que participen por primera vez que obtengan la aprobación de un mantenedor antes de poder activar cualquier flujo de trabajo. GitHub ofrece esta función de forma nativa en «Configuración > Acciones > Flujos de trabajo de pull requests de bifurcaciones».
En la práctica: El Trivy de marzo de 2026 se produjo al aprovechar pull_request_target. Los ingenieros pensaron que era seguro, ya que no se le permitiría ejecutar nada, pero eso no fue suficiente. El programa de relaciones públicas envió las credenciales al atacante, quien las utilizó para acceder a sus cuentas. Poco después, un atacante empecé a explorar GitHub especialmente para repositorios con pull_request_target activó y abrió unos cientos de PR en aproximadamente un día.
2. Evita utilizar «workflow_run» en repositorios públicos
workflow_run te permite encadenar flujos de trabajo de modo que uno posterior se active cuando finalice el anterior. El problema es que el flujo de trabajo posterior se ejecuta con permisos de escritura y acceso a secretos, independientemente de lo que haya activado el anterior, incluida una solicitud de incorporación de cambios (PR) de bifurcación de un colaborador externo.
Si un proveedor solicitud de incorporación El flujo de trabajo es vulnerable a la inyección de scripts, por lo que un atacante puede corromper el artefacto de salida a través de una solicitud de incorporación de cambios (PR). A continuación, el flujo de trabajo posterior consume el contenido controlado por el atacante en un contexto privilegiado con acceso a secretos, de modo que el contenido controlado por el atacante procedente de una PR no fiable ha llegado a un flujo de trabajo con acceso a secretos a través de un paso adicional. La ruta de ataque es más larga que pull_request_target pero llega al mismo sitio.
La mejor solución es evitar ese patrón. Si una implementación solo debe realizarse cuando se envían cambios a la rama «main», actívala directamente al enviar cambios a «main», en lugar de encadenarla a través de workflow_run. Si realmente necesitas workflow_run, comprueba github.event.workflow_run.event antes de realizar cualquier acción con privilegios. Si el desencadenante anterior fue un solicitud de incorporación En lugar de esperar a que un administrador te lo pida, mejor retírate antes de implementar o escribir nada.
trabajos:
implementar:
si: github.event.workflow_run.event == 'push'
zizmor se marcará workflow_run flujos de trabajo que realizan acciones con privilegios sin la comprobación de eventos, si deseas una detección automatizada en todo tu conjunto de repositorios.
3. Auditar los flujos de trabajo que utilizan otros desencadenantes con privilegios
Además de pull_request_target y workflow_run, presta atención a otros desencadenantes que se ejecutan con acceso a información confidencial. Entre ellos se incluyen comentar_publicación, temas, revisión de solicitud de incorporación de cambios, y comentario_de_revisión_de_una_solicitud_de_incorporación. Dado que todos se ejecutan con acceso secreto, pueden verse afectados por factores externos. Se aplican las mismas reglas de inyección de scripts, es decir, nunca se deben interpolar valores de estos eventos directamente en ejecutar: pasos. Hablaremos más sobre esto en la siguiente sección.
Manejo de entradas no fiables
1. Evita la inyección de código tratando todos los nombres de ramas, títulos de solicitudes de incorporación de cambios, mensajes de confirmación y cuerpos de incidencias como entradas no fiables
Se trata del mismo principio que la inyección SQL. Los valores controlados por el usuario que acaban en un comando de shell se interpretan como código, no como datos, por lo que nunca se deben interpolar github.* valores directamente en ejecutar: pasos. La solución consiste en asignar primero el valor a una variable de entorno y, a continuación, hacer referencia a esa variable en el script de shell:
# vulnerable
- run: echo "Branch is ${{ github.head_ref }}"
# safe
- run: echo "Branch is $BRANCH"
env:
BRANCH: ${{ github.head_ref }}
Cuando se asigna el valor a una variable de entorno, el intérprete lo lee como una cadena en tiempo de ejecución, en lugar de interpretarlo como sintaxis en el momento del análisis. Esto se aplica a cualquier dato procedente de una entrada controlada por el usuario: github.head_ref, github.event.pull_request.title, github.event.issue.body, github.event.commits[0].message, y valores de contexto similares. Un buen SAST como Aikido detectará esto y proporcionará la corrección en una solicitud de incorporación de cambios.
En su hábitat natural: En el Ataque de Ultralytics, un atacante nombró una rama con un comando curl que un flujo de trabajo interpoló directamente en un ejecutar: paso, ejecutándolo como código. El Ataque Nx/s1ngularity, detectado inicialmente por Aikido security, combinó esto con pull_request_target, donde una solicitud de incorporación de cambios a una rama obsoleta activó un flujo de trabajo vulnerable que provocó una fuga de GITHUB_TOKEN con permisos de lectura y escritura, que luego se utilizó para publicar paquetes npm maliciosos.
2. En el caso de los agentes de IA en flujos de trabajo personalizados, utiliza tokens de solo lectura y evita incluir la entrada sin procesar del usuario en las indicaciones
Los agentes de IA que se ejecutan en flujos de trabajo de GitHub Actions tienen el mismo acceso a secretos que cualquier otro paso. Si un agente procesa títulos de incidencias, descripciones de PR o mensajes de confirmación como parte de su solicitud, un atacante puede incluir instrucciones en ese texto y manipular al agente para que realice acciones privilegiadas, como modificar archivos o filtrar datos a través de cualquier herramienta a la que pueda acceder. Dado que no hay forma de evitar la inyección de solicitudes en los LLM, no permitas que los agentes de IA tengan acceso más allá de la lectura, y no permitas que reciban títulos de incidencias, descripciones de PR o mensajes de confirmación sin procesar como entrada de solicitud.
En la vida real: los investigadores de aikido lo demostraron con PromptPwnd: un título de incidencia malicioso introducido en un flujo de trabajo de la CLI de Gemini provocó que el agente escribiera secretos del repositorio en un hilo de incidencia público utilizando su propio gh acceso a las herramientas.
3. Tratar los resultados generados por los modelos de lenguaje grande (LLM) como datos no fiables
Cuando un flujo de trabajo utiliza un modelo de lenguaje grande (LLM) para generar un comando, un script o una ruta de archivo y pasa ese resultado directamente a un ejecutar: De este modo, se crea el mismo riesgo de inyección que al interpolar el nombre de una rama o el título de una solicitud de incorporación de cambios. No se garantiza que la salida de un modelo de lenguaje grande (LLM) sea segura, y un atacante que pueda manipular la solicitud puede influir en lo que se ejecuta. Tal y como comentamos en el punto anterior sobre la inyección de solicitudes, asigna primero la salida del LLM a una variable de entorno, valídala siempre que sea posible y nunca la introduzcas directamente en un comando de shell.
4. Nunca escribas datos no fiables en GITHUB_ENV o GITHUB_PATH
Dirigido a GITHUB_ENV establece las variables de entorno para todos los pasos posteriores del trabajo. Al escribir en GITHUB_PATH añade entradas a la variable PATH del sistema para todos los pasos posteriores. Si llega contenido no fiable a cualquiera de los dos archivos, un atacante podría establecer variables de entorno arbitrarias, como OPCIONES_DEL_NODO que provocan la ejecución de código. También podrían inyectar un archivo binario malicioso al principio de la ruta PATH, de modo que se ejecute en lugar de una herramienta de confianza. El patrón vulnerable consiste en un flujo de trabajo que descarga un artefacto o lee datos introducidos por el usuario y los escribe directamente en $GITHUB_ENV sin sanitizar. Trata todo lo que se escriba en estos archivos con la misma precaución que un ejecutar: paso.
Manipulación de objetos
5. Descomprime los archivos en un directorio temporal como /tmp en lugar del espacio de trabajo, para evitar sobrescribir los archivos del flujo de trabajo
Extraer un archivo directamente en el espacio de trabajo podría permitir que un archivo con contenido malicioso sobrescribiera archivos de flujo de trabajo, scripts o herramientas de los que dependen los pasos posteriores. Extraer a /tmp o un directorio aislado mantiene el contenido de los artefactos separado de todo aquello que tu flujo de trabajo considere de confianza. GitHub también admite la verificación mediante el resumen SHA256 si necesitas garantías de integridad más sólidas.
6. Excluir archivos secretos (.env, archivos de configuración, credenciales) de los artefactos cargados y evitar ruta: . tendencias que lo arrasan todo
El ruta: . patrón en un acciones/subir-artefacto El comando «step» sube todo lo que hay en el directorio de trabajo, lo que puede incluir .env archivos, archivos de configuración con credenciales incrustadas o secretos almacenados en caché que otros pasos hayan guardado en el disco. Sé claro sobre lo que estás subiendo para no publicar accidentalmente tus credenciales en Internet. Indica directorios o tipos de archivo concretos en lugar de incluir todo el espacio de trabajo, y añade .env, *.pem, y archivos similares en tu .gitignore y los patrones de exclusión de artefactos.
Referencias de acción mutables
7. Vincula todas las acciones de terceros a un SHA de confirmación completa, no a una etiqueta ni a una rama
Las etiquetas son útiles como atajo, pero la contrapartida es que no son estáticas. Las etiquetas y las ramas son mutables, lo que significa que el propietario de un repositorio puede reorientarlas hacia una confirmación diferente en cualquier momento, y eso es lo habitual con etiquetas como @main. Al hacer referencia a una versión concreta con usos: alguna-acción@v3, esperamos que la confirmación siga siendo la misma. Pero si la cuenta del responsable de la acción se ve comprometida, un atacante puede redirigir esa etiqueta a una confirmación maliciosa y todos los flujos de trabajo posteriores la incorporarán en la siguiente ejecución sin una solicitud de incorporación de cambios ni ningún otro aviso. Para evitarlo, la mejor práctica consiste en fijar en su lugar el SHA completo de la confirmación: usos: alguna-acción@abc123def456..... Por supuesto, esto puede resultar un poco molesto, así que puedes utilizar Dependabot, Renovate o pinact para mantener actualizados los SHA fijados. Los archivos de bloqueo nativos están incluidos en la hoja de ruta de GHA, así que esperamos que estén disponibles para 2027.
En la vida real: En marzo de 2025, los atacantes redirigieron 76 de las 77 etiquetas de versión en trivy a revisiones maliciosas que contenían un programa de robo de información. Todos los flujos de trabajo que hacían referencia a esas etiquetas por su nombre incorporaban automáticamente el código malicioso.
8. Analizar las acciones de terceros antes de la adopción
Antes de añadir un usos: Dedica dos minutos a revisar el repositorio de la acción. Comprueba si el creador está verificado por GitHub, cuándo se actualizó por última vez el repositorio, cuántos colaboradores tiene y cuál es su puntuación en la OpenSSF Scorecard. Una acción muy utilizada, creada por un único mantenedor no verificado y sin actividad reciente, es un objetivo muy atractivo para el secuestro de cuentas.
9. Da preferencia a las acciones con menos dependencias transitivas
Cuantas más dependencias haya, más vulnerable serás a ataques a la cadena de suministro, así que, cuando haya opciones, elige acciones con menos dependencias. Una acción puede hacer referencia a otras acciones, y esas dependencias transitivas se resuelven en tiempo de ejecución. Fijar el SHA de tu dependencia directa no te protege si esta incorpora sus propias dependencias de forma mutable.
En la naturaleza: El tj-acciones de compromiso se propaga en parte a través de este mecanismo. Los flujos de trabajo posteriores vinculados a tj-actions/changed-files, pero archivos modificados referenciado de forma transitiva reviewdog/action-setup por una etiqueta mutable, por lo que, cuando se vio comprometido el sistema Reviewdog, todas las tuberías posteriores ejecutaron el código malicioso.
Dependencias de paquetes modificables
10. Especificar explícitamente las versiones de los paquetes de npm y PyPI
Las gamas de versiones flotantes como ^1.2.0 o >=2.0.0 significa que tu flujo de trabajo instala la última versión compatible en el momento de la ejecución. Si un paquete se ve comprometido y se publica una nueva versión maliciosa dentro de tu rango, tu flujo de trabajo la incorporará automáticamente en la siguiente ejecución. Fijar a versiones exactas (1.2.3) para que tu flujo de trabajo solo instale lo que hayas seleccionado explícitamente. No te dejes llevar por el rango.
En la naturaleza: El ataque de Ultralytics demostró cómo una versión de un paquete comprometida publicada en PyPI puede llegar a flujos de trabajo que no están fijados. La primera versión maliciosa estuvo activa durante horas antes de ser detectada, tiempo suficiente para afectar a las compilaciones que incorporaban dependencias flotantes.
11. Establece una edad mínima de publicación siempre que tu gestor de paquetes lo permita (pnpm, yarn)
Incluso con las versiones fijadas, un paquete malicioso recién publicado puede coincidir con una versión concreta a la que decidas actualizar más adelante. La configuración de la antigüedad mínima de las versiones indica al gestor de paquetes que rechace los paquetes publicados hace menos de un tiempo determinado, normalmente 72 horas, lo que da tiempo a la comunidad para detectar y notificar versiones maliciosas antes de que lleguen a tus compilaciones. pnpm y yarn admiten esta función de forma nativa, pero npm aún no. Aikido Safe Chain puede solucionar esto para npm (véase más abajo).
12. Verificar el origen de los paquetes mediante certificados, cuando estén disponibles
Algunos registros de paquetes admiten ahora certificados de procedencia, que consisten en registros criptográficos que vinculan un paquete publicado con la confirmación del código fuente específica y el proceso de compilación que lo generó. La verificación de estos certificados antes de instalar un paquete confirma que este se ha compilado a partir del código fuente que indica. npm admite esta función para los paquetes publicados a través de GitHub Actions. Se trata de una práctica aún reciente y la compatibilidad con las herramientas no es total, pero merece la pena habilitarla siempre que tu registro y tu gestor de paquetes la admitan.
Tratamiento de información confidencial
13. Indica las claves mediante variables de entorno, nunca mediante argumentos de la línea de comandos
Los argumentos de la línea de comandos son visibles en los listados de procesos, por lo que otros procesos del ejecutor que tengan acceso a /proc puede leerlos. Al pasar un secreto como variable de entorno, este no aparece en la tabla de procesos. En tu flujo de trabajo, configura el secreto en un env: bloque y referencia $SECRET_NAME en el comando del intérprete de comandos en lugar de ${{ secrets.MY_SECRET }} en línea.
En la práctica: tj-actions filtró información confidencial al registrarla en el archivo de registro (el problema de «echo» y el enmascaramiento), y el Trivy provocó el robo de un PAT. La gestión de la información confidencial consiste en limitar el acceso a dicha información en todo el sistema, de modo que, si algo sale mal, un atacante no pueda hacerse con credenciales válidas.
14. Limita los secretos a nivel de repositorio a entornos específicos de GitHub siempre que sea posible
Los entornos de GitHub te permiten restringir el acceso a los secretos mediante reglas de protección de la implementación, de modo que un secreto como CONTRASEÑA_DE_LA_BASE_DE_DATOS_PROD solo es accesible para los flujos de trabajo destinados al entorno de producción. Sin esta configuración, cualquier flujo de trabajo del repositorio puede leer cualquier secreto a nivel de repositorio. Puedes configurarlo en Ajustes > Entornos.
15. Defina los secretos en el flujo de trabajo a nivel de paso, no a nivel de trabajo
Limitar el alcance de los datos confidenciales a los pasos concretos de una tarea que los requiera aplica el principio del privilegio mínimo para reducir el alcance de los daños en caso de que una acción se vea comprometida. Un dato confidencial declarado a nivel de tarea env: El bloque es legible en cada paso de ese trabajo, incluidas las acciones de terceros.
En estado salvaje: En el ataque Shai-Hulud, los tokens con ámbito de flujo de trabajo se reutilizaron entre las víctimas. Un ámbito más restringido habría limitado el alcance del impacto.
16. Utiliza OIDC para obtener credenciales de nube de corta duración en lugar de claves secretas estáticas de larga duración, siempre que el proveedor de la nube lo admita (AWS, Azure, GCP)
Las credenciales estáticas de la nube almacenadas como secretos de GitHub tienen una validez indefinida, por lo que, si son robadas, el riesgo de sufrir daños es muy elevado. OIDC permite que tu flujo de trabajo solicite directamente un token de corta duración a AWS, Azure o GCP, limitado al ámbito del trabajo y válido durante unos minutos, por lo que no hay credenciales que un atacante pueda robar. AWS, Azure y GCP admiten esta función de forma nativa. Para configurarlo, es necesario establecer una relación de confianza entre tu proveedor de nube y el punto final OIDC de GitHub.
17. Exigir la aprobación humana en las ejecuciones de flujos de trabajo que utilicen entornos de producción
Configura tu entorno de GitHub para que sea obligatorio que alguien revise un flujo de trabajo antes de que pueda acceder a los secretos de un entorno o realizar una implementación en él. Esta opción resulta más adecuada para equipos pequeños o aquellos que realizan entregas con poca frecuencia. Para equipos más grandes, la versión más escalable es OIDC con credenciales de corta duración.
18. Evita imprimir o mostrar valores confidenciales, incluso en la salida de depuración
GitHub oculta los valores de los secretos conocidos en los registros, pero solo en el caso de coincidencias exactas, por lo que si un secreto se codifica en Base64 o se divide en dos llamadas a «echo», el ocultamiento no funciona. La norma más segura es simplemente no mostrar nunca los secretos. Si necesitas comprobar que un secreto está configurado, comprueba que haya una cadena no vacía en lugar de mostrar el valor.
Corredores
19. No utilices runners autohospedados en repositorios públicos
Cualquiera puede abrir una solicitud de incorporación de cambios (PR) en un repositorio público, lo que significa que, en teoría, cualquiera puede activar la ejecución de un flujo de trabajo. La configuración predeterminada de aprobación de GitHub para los colaboradores noveles mitiga este riesgo en los ejecutores alojados en GitHub, donde el entorno es, de todos modos, efímero y aislado. En un runner autohospedado, una configuración de aprobación mal configurada o excesivamente permisiva significa que esa misma solicitud de pull (PR) desencadena la ejecución de código en tu infraestructura. GitHub recomienda utilizar runners alojados en GitHub para repositorios públicos y endurecer la política de aprobación para «exigir aprobación para todos los colaboradores externos».
En la vida real: unos investigadores llevaron a cabo un ataque a la cadena de suministro contra PyTorch enviando una solicitud de incorporación de cambios trivial que activó un flujo de trabajo en un ejecutor autohospedado, lo que les permitió obtener acceso de root a la máquina.
20. Utiliza subprocesos efímeros en lugar de subprocesos estáticos persistentes
Un ejecutor estático conserva el estado entre tareas, lo que significa que una tarea comprometida puede dejar archivos maliciosos, binarios modificados o cachés contaminados que afecten a las siguientes ejecuciones en esa máquina. Los ejecutores efímeros se inician desde cero y se eliminan tras cada tarea. Utiliza Actions Runner Controller para configuraciones basadas en Kubernetes, o pasa el --efímero marcar al registrar manualmente a un corredor.
En su hábitat natural: Shai-Hulud registró ejecutables persistentes autohospedados en repositorios comprometidos y los utilizó como un canal C2 persistente, invisible para la supervisión de la red, ya que todo el tráfico fluía a través de github.com.
21. Limitar la salida de la red de runners a una lista de permitidos
La acción más peligrosa de un flujo de trabajo comprometido suele ser la filtración de información confidencial a un servidor controlado por el atacante. Limitar el acceso de red saliente únicamente a los dominios que tu flujo de trabajo realmente necesita dificulta considerablemente esa tarea. Tanto Harden-Runner como bullfrog funcionan en runners alojados en GitHub. En el caso de los runners autohospedados, las reglas de cortafuegos a nivel de red logran el mismo objetivo.
Si utilizas GitHub Enterprise con runners autohospedados, las listas de IP permitidas para los tokens añaden un control en sentido contrario. Restringen las direcciones IP que pueden utilizar un token, de modo que un token robado no pueda utilizarse desde la infraestructura de un atacante.
Permisos de los tokens
22. Establecer como predeterminado GITHUB_TOKEN permisos de solo lectura a nivel de organización o de repositorio
El GITHUB_TOKEN está disponible automáticamente en cada ejecución del flujo de trabajo. De forma predeterminada, cuenta con amplios permisos de lectura y escritura en todo el repositorio, por lo que cualquier flujo de trabajo comprometido podría escribir en tu repositorio, crear versiones o aprobar solicitudes de incorporación de cambios. Configura el valor predeterminado como «solo lectura» en Ajustes > Acciones > General y, a continuación, concede permisos de escritura de forma explícita solo cuando sea necesario.
23. Declarar explícitamente permisos: bloqueos a nivel de flujo de trabajo o de tarea para limitar tareas concretas
Establecer un valor predeterminado de solo lectura a nivel de organización crea la configuración predeterminada, pero es evidente que algunas tareas requieren más permisos. Cuando una tarea necesite un acceso con privilegios elevados, declare un permisos: bloquear a nivel de tarea en lugar de a nivel de flujo de trabajo. De este modo, el token con privilegios elevados se limita únicamente a esa tarea, y el resto de tareas del flujo de trabajo siguen siendo de solo lectura.
trabajos:
implementar:
permisos:
contenidos: lectura
token de identificación: escrituraEn la práctica: los ataques de tipo «tj-actions», Trivy y «prt-scan» se beneficiaron de que los tokens tuvieran más permisos de los necesarios. Restringir los permisos de los tokens reduce el alcance del impacto en todos los aspectos.
Configuración de la organización y del repositorio
24. Desactivar la posibilidad de que las acciones aprueben las solicitudes de incorporación de cambios
De forma predeterminada, GitHub permite que los flujos de trabajo aprueben las solicitudes de incorporación de cambios utilizando el GITHUB_TOKEN. Esto significa que un flujo de trabajo comprometido podría aprobar sus propios cambios maliciosos sin pasar por ningún proceso de revisión. Desactiva esta opción en Configuración > Acciones > General > «Permitir que GitHub Actions cree y apruebe solicitudes de incorporación de cambios». (Algunos equipos mantienen esta opción activada para Dependabot , pero es mejor asignarle a Dependabot cuenta de bot específica con permisos explícitos de revisor, en lugar de habilitar la aprobación del flujo de trabajo para toda la organización.)
25. Limitar las fuentes de acciones a creadores verificados o repositorios específicos
La configuración predeterminada de GitHub permite que cualquier acción publicada en GitHub Marketplace se utilice en tus flujos de trabajo. Restringir las fuentes a creadores verificados o a una lista de permitidos específica implica que una acción maliciosa recién publicada no puede incorporarse a tus flujos de trabajo sin una aprobación explícita. En su lugar, los desarrolladores deben solicitar la aprobación de quien sea el responsable de la configuración de tu organización de GitHub (normalmente la plataforma o el equipo de DevOps), quien puede añadirla a la lista de permitidos. Configura esto en Ajustes > Acciones > General > «Permitir acciones y flujos de trabajo reutilizables».
En la vida real: Las vulnerabilidad tj-actions afectó a 23 000 repositorios, en parte porque los equipos no tenían restricciones sobre las acciones que podían incorporar.
26. Supervisa los registros inesperados de runners autohospedados y los repositorios públicos de nueva creación en tu organización
Un token robado permite a un atacante registrar un «runner» malicioso para instalar una puerta trasera persistente. Además, los atacantes suelen crear repositorios públicos para almacenar las credenciales robadas. Tanto el registro de «runners» como la creación de repositorios son eventos que tu equipo debe detectar de inmediato, pero GitHub no envía alertas sobre ellos de forma predeterminada. La solución consiste en supervisarlos manualmente. Transmite el registro de auditoría de tu organización a un SIEM y configura alertas sobre self_hosted_runners.register eventos y la creación de repositorios. Si no dispones de un SIEM, puedes consultar el registro de auditoría a través de la API de GitHub o comprobarlo manualmente en «Configuración > Registro de auditoría».
En el entorno real: En el ataque Shai-Hulud, los equipos comprometidos se registraron como ejecutores autohospedados denominados SHA1HULUD, y las credenciales robadas se utilizaron para crear repositorios públicos que sirvieron como depósitos de exfiltración. La monitorización de ambos aspectos habría permitido detectar la campaña en una fase temprana.
27. Utilice CODEOWNERS para exigir una revisión de seguridad de los cambios en .github/workflows/
Los archivos de flujos de trabajo son código que se ejecuta con acceso a tus secretos y tokens. Sin normas de propiedad explícitas, cualquier desarrollador con acceso de escritura al repositorio puede modificar un flujo de trabajo e integrarlo sin que se haya realizado una revisión de seguridad. Añade una entrada CODEOWNERS que apunte a .github/workflows/ a un revisor o equipo que comprenda las consideraciones de seguridad, y combínalo con reglas de protección de ramas que requieran la aprobación de los CODEOWNERS antes de la fusión.
Protege los flujos de trabajo de GitHub Actions con Aikido
Aikido detecta flujos de trabajo de GitHub Actions que presentan vulnerabilidades y ayuda a los desarrolladores a solucionarlas antes de que sean objeto de ataques.
Detecta problemas como:
- Uso inadecuado de
pull_request_target - Inyección de código a través de fuentes no fiables
github.*entrada - Inyección de plantillas y indicaciones en flujos de trabajo basados en IA
- Acciones de terceros no fijadas
- Demasiado privilegiado
GITHUB_TOKENpermisos - Gestión de información confidencial con riesgos en los flujos de trabajo
El aikido también puede:
- Crear automáticamente solicitudes de incorporación de cambios
- Detectar patrones de flujo de trabajo poco seguros en los repositorios
- Marca las referencias mutables de GitHub Actions que deben fijarse a un SHA de confirmación completo
La cadena de seguridad Aikido ayuda a proteger las instalaciones de paquetes de las siguientes maneras:
- Bloqueo de paquetes maliciosos conocidos de npm y PyPI
- Aplicación de las políticas sobre la edad mínima para la venta de paquetes
Por ejemplo, Aikido detecta entradas de usuario no validadas en ejecutar: sigue estos pasos y sugiere automáticamente el patrón de variable de entorno más seguro.
Listo para proteger los flujos de trabajo de GitHub Actions
Ten a mano esta lista de comprobación mientras trabajas en la seguridad de los flujos de trabajo de GitHub Actions. Intenta poner en práctica cuanto antes las medidas que puedas llevar a cabo en solo unos minutos y compártela con tus compañeros de equipo para que todos estén al tanto de los cambios.
Preguntas frecuentes: Seguridad de GitHub Actions
¿Cuál es la forma más habitual en que se aprovechan las vulnerabilidades de los flujos de trabajo de GitHub Actions?
La inyección de scripts es el vector más frecuente. Los atacantes introducen código malicioso en los nombres de las ramas, los títulos de las solicitudes de incorporación de cambios o el cuerpo de los incidencias, y los flujos de trabajo que interpolan esos valores directamente en ejecutar: Los pasos se ejecutan como comandos de shell. Al fijar las acciones para confirmar los SHA y utilizar variables de entorno en lugar de la interpolación en línea, se reduce en gran medida esta vulnerabilidad.
¿Qué es pull_request_target ¿Y por qué es peligroso?
pull_request_target es un desencadenador de flujo de trabajo que se ejecuta con acceso a los secretos del repositorio base, incluso cuando la solicitud de incorporación de cambios (PR) que lo activa proviene de una bifurcación. Dado que cualquiera puede abrir una solicitud de incorporación de cambios en un repositorio público, cualquier flujo de trabajo que utilice este desencadenador expone sus secretos a los colaboradores externos. Evítalo por completo en los repositorios públicos.
¿Qué significa «asignar acciones a un SHA de confirmación» y por qué es importante?
La mayoría de los flujos de trabajo hacen referencia a acciones de terceros mediante etiquetas, como usos: alguna-acción@v3. Las etiquetas son modificables, por lo que, si la cuenta de un responsable de mantenimiento de una acción se ve comprometida, un atacante puede redirigir esa etiqueta de forma silenciosa hacia código malicioso. Anclarla a un SHA de una confirmación completa como usos: some-action@abc123... significa que tu flujo de trabajo solo ejecuta exactamente lo que has revisado.
¿Debería utilizar runners autohospedados en repositorios públicos?
No. Cualquiera puede abrir una solicitud de incorporación de cambios en un repositorio público y activar un flujo de trabajo. En los runners alojados en GitHub, esto es manejable porque el entorno es efímero y está aislado. En un runner autohospedado, una política de aprobación mal configurada implica que los colaboradores externos pueden ejecutar código directamente en tu infraestructura.
¿Qué es OIDC y por qué es mejor que almacenar las credenciales de la nube como secretos?
Las credenciales estáticasalmacenadas como secretos de GitHub son válidas de forma indefinida, por lo que un secreto robado sigue siendo peligroso mucho tiempo después de la filtración. OIDC permite que tu flujo de trabajo solicite a AWS, Azure o GCP un token de corta duración, limitado a esa tarea concreta y válido durante unos minutos. No hay credenciales de larga duración que puedan ser robadas.

