Ce que fait cet outil
GitHub est souvent la première porte d'entrée dans le cloud : un seul token d'accès personnel volé donne à l'attaquant votre code source, vos pipelines CI/CD et — via les secrets Actions — vos comptes cloud. Le journal d'audit de l'organisation en garde l'essentiel : qui s'est authentifié avec quel token, depuis quelle IP, a cloné quoi, a modifié quel paramètre.
Cet outil lit ces exports dans votre navigateur, applique un ensemble de règles de détection publiées et donne un verdict global (Sain / Suspect / Compromis), les constats avec leurs preuves et techniques MITRE ATT&CK, une chronologie de l'incident, un pivot par entité (acteurs, tokens, IP, dépôts, workflows, runners, applications) et un plan de remédiation.
Ce que vous pouvez déposer
- Journal d'audit d'organisation ou d'entreprise exporté depuis l'interface web (JSON ou CSV).
- Sortie de l'API REST (GET /orgs/{org}/audit-log, avec include=all pour les événements Git), pages concaténées ou non.
- Fichiers de streaming du journal d'audit (Amazon S3, Azure Blob, Google Cloud Storage) : arborescence YYYY/MM/DD/HH/MM/<uuid>.json.log.gz, JSON lines compressé en gzip — déposez le dossier entier.
- Export des événements Git (export-<entreprise>-<timestamp>.json.gz) : git.clone, git.fetch et git.push avec les métadonnées de token.
- Archives de logs d'exécution GitHub Actions (le ZIP de « Download log archive »).
- Alertes secret scanning telles que renvoyées par l'API REST (JSON).
Ce qui est détecté
Les détections sont des données, pas du code : chaque règle est une entrée JSON relisible (conditions, seuil ou référence, gravité, techniques ATT&CK, remédiation) avec des cas de test positifs et négatifs. Les règles de cette version :
| Règle | Gravité | ATT&CK |
|---|---|---|
Une étape de workflow encode ou exfiltre des secretsactions-secret-exfil | Critique | T1552.001, T1567 |
Token utilisé depuis un nouveau paystoken-new-country | Élevée | T1550.001, T1078.004 |
Clonage massif de dépôtsgit-clone-burst | Élevée | T1213.003 |
Dépôt rendu publicrepo-made-public | Élevée | T1567 |
Dépôt transféré à l'extérieurrepo-transferred | Élevée | T1537 |
Plusieurs dépôts supprimésrepo-mass-delete | Élevée | T1485 |
Propriétaire d'organisation ou d'entreprise ajoutéowner-granted | Élevée | T1098.003 |
Exigence de double authentification désactivéetwo-factor-disabled | Élevée | T1556 |
SSO SAML désactivé ou reconfigurésso-changed | Élevée | T1556 |
Liste d'adresses IP autorisées désactivéeip-allowlist-disabled | Élevée | T1562.007 |
Streaming du journal d'audit supprimé ou modifiéaudit-stream-changed | Élevée | T1562.008 |
Protection de branche ou ruleset supprimébranch-protection-removed | Élevée | T1562 |
Protection d'environnement de déploiement suppriméeenvironment-protection-removed | Élevée | T1562 |
Compte actif depuis un nouveau paysactor-new-country | Moyenne | T1078.004 |
Nombreuses archives de code téléchargéesarchive-download-burst | Moyenne | T1213.003 |
Accès admin donné à un collaborateurcollaborator-admin | Moyenne | T1098 |
Restrictions des applications tierces désactivéesoauth-restrictions-disabled | Moyenne | T1562 |
Politique des tokens d'accès personnels affaibliepat-policy-weakened | Moyenne | T1562 |
Protection de branche contournéebranch-protection-override | Moyenne | T1562 |
Runner auto-hébergé enregistréself-hosted-runner-registered | Moyenne | T1072 |
Longue chaîne encodée affichée dans un log de workflowactions-encoded-output | Moyenne | T1552.001, T1027 |
Le secret scanning a trouvé un secret divulguésecret-leak-alert | Moyenne | T1552.001 |
Protection push des secrets contournéepush-protection-bypass | Moyenne | T1552.001 |
Clé SSH ou clé de déploiement ajoutéedeploy-key-added | Moyenne | T1098.004 |
Token utilisé depuis une nouvelle adresse IPtoken-new-ip | Faible | T1550.001 |
Fork des dépôts privés autoriséprivate-forking-enabled | Faible | T1537 |
Secret Actions créé ou modifiéactions-secret-created | Faible | |
Exécution de workflow depuis une branche jamais vueworkflow-new-branch | Faible | T1677 |
Token fine-grained demandé ou autoriséfine-grained-token-granted | Faible | T1550.001 |
Application installée ou application OAuth approuvéeapp-authorized | Faible | T1528 |
Webhook crééwebhook-created | Faible | T1567 |
Comment le verdict est décidé
- Compromis : au moins un constat critique (par exemple des secrets affichés par un workflow), ou plusieurs constats distincts de gravité élevée sur le même acteur, token ou adresse IP.
- Suspect : au moins un constat de gravité élevée ou moyenne.
- Sain : aucun constat au-dessus de faible. Cela ne couvre que ce que contiennent les journaux — vérifiez les notes de couverture (affichage des IP, événements Git, métadonnées de token) et la période couverte.
Quand des clés cloud ont fuité
Les secrets Actions sont le plus souvent des identifiants cloud. Quand ils apparaissent dans les preuves, l'étape suivante est le compte cloud lui-même — poursuivez avec les outils frères de cette série :
Limites
- Le journal d'audit n'enregistre pas le contenu des fichiers : un workflow modifié est déduit des exécutions (nouvelle branche, secrets affichés dans le log), pas du diff. Vérifiez vous-même l'historique de .github/workflows.
- Sans « Display IP addresses », les exports n'ont pas d'actor_ip et la localisation est limitée : les détections basées sur l'IP ne peuvent pas se déclencher.
- Les événements Git (clones, fetchs, pushs) ne sont conservés que 7 jours et ne figurent pas dans l'export JSON/CSV de l'interface web : sans eux, le clonage massif est invisible.
- Les règles sont des heuristiques avec des seuils (10 dépôts clonés en une heure environ, une référence de 24 heures pour les nouvelles IP et nouveaux pays) : adaptez-les à votre organisation. Un verdict sain n'est pas une preuve d'absence.
- Le tableau liste les 100 000 premiers événements ; tous sont analysés. Les journaux de sécurité des comptes personnels ne sont pas couverts.
FAQ
Mes journaux d'audit sont-ils envoyés quelque part ?
Non. L'analyseur est écrit en Rust, compilé en WebAssembly, et s'exécute dans un Web Worker de votre navigateur ; les fichiers sont lus en flux depuis le disque et décompressés localement. Il n'y a aucun point d'envoi, et l'outil fonctionne hors ligne une fois la page chargée.
Comment savoir si un token GitHub a été volé ?
Cherchez le même hashed_token utilisé depuis une nouvelle adresse IP ou un nouveau pays, des rafales de git.clone sur de nombreux dépôts, et une activité du token hors des horaires de son propriétaire. Le journal d'audit enregistre hashed_token, programmatic_access_type et token_scopes pour les événements authentifiés par token ; cet outil établit une référence par token et signale les nouvelles localisations.
Comment retrouver le token correspondant à un hashed_token ?
hashed_token est le SHA-256 du token encodé en base64. Si vous avez un token candidat, calculez-le avec : echo -n TOKEN | openssl dgst -sha256 -binary | base64 — puis cherchez hashed_token:"VALEUR" dans le journal d'audit. Les propriétaires d'entreprise peuvent aussi exporter l'inventaire des identifiants, qui liste les valeurs hashed_token.
Pourquoi je ne vois pas d'événements git.clone ?
Les événements Git ne figurent pas dans l'export JSON/CSV du journal d'audit de l'interface web. Récupérez-les via le menu « Export Git Events » de l'entreprise, l'API REST avec include=git ou include=all, ou le streaming du journal d'audit — et vite : ils ne sont conservés que 7 jours.
Un workflow peut-il divulguer des secrets alors que GitHub les masque ?
Oui. GitHub remplace les valeurs connues des secrets par *** dans les logs, mais un script qui les encode en base64 (deux fois, ou inversés) affiche une chaîne non masquée qui se décode en secret. Cet outil signale les scripts qui envoient des secrets ou l'environnement dans des encodeurs ou vers des points externes, ainsi que les longues chaînes encodées dans la sortie.
Est-ce un outil officiel de GitHub ?
Non. C'est un outil indépendant, ni affilié à GitHub, Inc. ni approuvé par elle. Il lit les formats d'export documentés du journal d'audit.