¿Organización de GitHub comprometida? Guía de respuesta
Qué hacer si tu organización de GitHub está comprometida: conserva el registro de auditoría, contén tokens y workflows, acota con eventos Git y salta al cloud.
En resumen. Una organización de GitHub comprometida suele ser un incidente de cadena de suministro en su fase inicial. Alguien tiene un token, una clave o una sesión de propietario, y tu código fuente, tu CI/CD y tus credenciales cloud están a su alcance. Trabaja en este orden: conserva el registro de auditoría y los eventos Git (los eventos Git se conservan 7 días), contén (revoca credenciales, detén workflows, elimina la persistencia), determina el alcance con las evidencias y, por último, salta a las cuentas cloud cuyas claves estaban en los secretos de Actions. Puedes revisar las exportaciones con el analizador gratuito en el navegador, que no sube nada.
GitHub es a menudo el primer punto de apoyo de un atacante en el cloud. Un solo token de acceso personal (PAT) robado abre los repositorios privados, los workflows que despliegan en producción y los secretos que esos workflows manejan. Esta guía es el punto de entrada de la serie. Cada sección resume un escenario y enlaza con la guía que lo trata en profundidad.
Cómo se comprometen las organizaciones de GitHub
Casi todos los incidentes que veo empiezan por uno de estos vectores:
| Punto de entrada | Evidencia típica en el registro de auditoría | Guía |
|---|---|---|
| Token de acceso personal robado por un infostealer o filtrado en el código | mismo hashed_token desde un país / IP nuevo, ráfagas de git.clone | Token de GitHub filtrado |
| Token de una OAuth app o de una GitHub App robado a un tercero | actividad de API de una integración, repositorios listados y descargados | Token de GitHub filtrado |
| Workflow envenenado o action de terceros comprometida | workflows.created_workflow_run en una rama nueva, blobs codificados en los logs de ejecución | Fuga de secretos de Actions |
| Runner self-hosted malicioso o comprometido | org.register_self_hosted_runner, jobs en runners desconocidos | Seguridad de los runners self-hosted |
| Toma de control de una cuenta de propietario | org.update_member a admin, org.disable_two_factor_requirement | Toma de control de la organización |
No es solo teoría. En abril de 2022, GitHub informó de que un atacante había usado tokens de usuario OAuth robados, emitidos para Heroku y Travis CI, para listar y descargar repositorios privados de decenas de organizaciones. En marzo de 2025, la CISA publicó una alerta sobre el compromiso de tj-actions/changed-files (CVE-2025-30066): una action muy popular se modificó para que imprimiera los secretos de CI en los logs de los workflows. En septiembre de 2025, la alerta de la CISA sobre el ecosistema npm describió un malware que recolectaba PAT de GitHub y claves cloud en los entornos de los desarrolladores.
Paso 1: conserva primero las evidencias
La retención marca el orden de trabajo. GitHub conserva los eventos de auditoría de la organización durante 180 días, pero los eventos Git solo siete días. Por defecto, los logs de Actions se conservan 90 días, y cualquiera con acceso de escritura al repositorio puede borrar los logs de una ejecución. Un atacante que tenga tu token puede, por tanto, borrar las evidencias más útiles.
Antes de tocar nada:
- Exporta el registro de auditoría de la organización en JSON para toda la ventana sospechosa, más unas semanas previas como referencia.
- En GitHub Enterprise Cloud, recupera los eventos Git (
git.clone,git.fetch,git.push) mediante la API REST coninclude=all, o usa el menú "Export Git Events" de la empresa. - Descarga el archivo de logs de cada ejecución de workflow sospechosa.
- Si haces streaming del registro de auditoría a S3, Azure Blob o GCS, copia las carpetas
YYYY/MM/DD/HH/MM/pertinentes. - Guarda las copias en solo lectura y calcula su hash.
La guía de exportación recorre cada fuente paso a paso e indica qué plan necesita cada una.
Paso 2: contén
El propio tutorial de respuesta a incidentes de GitHub recomienda elegir las medidas de contención en función de la amenaza y no aplicarlas todas a ciegas. Las medidas que frenan la mayoría de los incidentes reales son estas:
- Revoca las credenciales implicadas. Si tienes el token literal, cualquiera puede revocarlo con la API de revocación de credenciales. Si no, lo revoca su propietario, o un propietario de la organización revoca su autorización SSO. Comprueba si hay un infostealer en el equipo del desarrollador antes de emitir un token nuevo.
- Detén el pipeline. Cancela los workflows en curso, borra las ramas del atacante y, si hace falta, desactiva Actions en los repositorios afectados.
- Elimina la persistencia. Busca deploy keys, claves SSH, webhooks, GitHub Apps, aprobaciones de OAuth apps, colaboradores externos y runners self-hosted añadidos durante la ventana del incidente.
- Rota todos los secretos que podían leer los workflows afectados, no solo los que viste impresos.
Paso 3: determina el alcance con el registro de auditoría
Determinar el alcance responde a tres preguntas: qué credencial, qué tocó, qué cambió.
Qué credencial
Los eventos autenticados con token llevan hashed_token, programmatic_access_type y token_scopes. GitHub documenta cómo identificar los eventos del registro de auditoría realizados por un token de acceso. Agrupa por hashed_token en lugar de por actor. Un token robado pertenece a un usuario legítimo, así que su actividad se mezcla con la de ese usuario, pero las IP y los países del atacante son distintos.
Qué tocó
Los eventos Git te dicen qué repositorios se clonaron y cuándo. Diez o más repositorios distintos clonados desde una misma IP en una hora no es el comportamiento normal de un desarrollador. Consulta cómo detectar la exfiltración de repositorios para conocer las demás vías de exfiltración: repo.download_zip, cambios de visibilidad y transferencias.
Qué cambió
Filtra por las acciones que debilitan un control o añaden acceso. Esta tabla recoge el conjunto mínimo:
| Ámbito | Acciones que revisar |
|---|---|
| Propietarios y administradores | org.update_member / org.add_member con permission: admin, business.add_admin |
| Autenticación | org.disable_two_factor_requirement, org.disable_saml, org.update_saml_provider_settings |
| Red | ip_allow_list.disable, ip_allow_list.disable_for_installed_apps |
| Registro | audit_log_streaming.destroy, audit_log_streaming.update |
| Integridad del código | protected_branch.destroy, repository_ruleset.destroy, protected_branch.policy_override |
| CI/CD | environment.remove_protection_rule, org.register_self_hosted_runner, *.create_actions_secret |
| Persistencia | public_key.create, hook.create, integration_installation.create |
El artículo sobre la protección de ramas y el artículo sobre la toma de control explican cómo interpretar cada una de ellas.
Paso 4: sigue los secretos hasta el cloud
Los secretos de Actions son, en su mayoría, credenciales cloud. Cuando se filtran, el incidente no ha hecho más que empezar. Las siguientes evidencias están en CloudTrail, en los registros de auditoría de Google Cloud o en los registros de actividad de Azure. El artículo sobre el salto al cloud cubre ese paso y enlaza con las herramientas hermanas para AWS, Google Cloud y Azure.
Qué papel juega el analizador de este sitio
La herramienta GitHub Forensics lee las exportaciones descritas arriba: el JSON / CSV de la interfaz, las páginas de la API REST, los ficheros de streaming .json.log.gz, la exportación de eventos Git, los ZIP de logs de Actions y las alertas de secret scanning. Evalúa 31 reglas de detección publicadas y devuelve un veredicto (Ningún indicio de compromiso, Actividad sospechosa o Comprometida), hallazgos con sus evidencias y técnicas de ATT&CK, una cronología y una lista de remediación. Todo se ejecuta en local con WebAssembly.
Las reglas son heurísticas con umbrales, y un veredicto "Ningún indicio de compromiso" solo cubre lo que contiene la exportación. El artículo sobre las limitaciones enumera lo que el registro de auditoría no registra nunca. Si antes quieres ver qué aspecto tiene un análisis terminado, el recorrido ficticio de northwind-labs repasa el incidente de ejemplo hallazgo por hallazgo.
Preguntas frecuentes
¿Qué es lo primero que hay que hacer cuando una organización de GitHub está comprometida?
Exporta las evidencias antes de cambiar nada: el registro de auditoría de la organización (JSON) y, en Enterprise Cloud, los eventos Git, que solo se conservan siete días. Descarga los archivos de logs de las ejecuciones de workflows sospechosas. Después revoca los tokens implicados y detén los workflows maliciosos.
¿Registra GitHub qué repositorios se han clonado?
Sí, como eventos git.clone, git.fetch y git.push. Solo puedes obtenerlos mediante la API REST con include=git o include=all, mediante el streaming del registro de auditoría o mediante la exportación de eventos Git de la empresa, y solo en GitHub Enterprise Cloud. Se conservan siete días.
¿Puedo investigar un incidente de GitHub sin un SIEM?
Sí. La exportación del registro de auditoría, la exportación de eventos Git y los archivos de logs de Actions son simples ficheros JSON, gzip y ZIP. Puedes leerlos con jq o soltarlos en un analizador offline como el de este sitio, que se ejecuta íntegramente en el navegador.