Limites du journal d'audit GitHub : rétention, lacunes
Ce que le journal d'audit GitHub n'enregistre pas : rétention de 180 et 7 jours, API et événements Git selon l'offre, IP masquées, ni contenus ni secrets lus.
En bref. Le journal d'audit est la meilleure preuve dont vous disposez côté GitHub, mais il a des limites strictes. Rétention : 180 jours pour les événements d'audit, 7 jours pour les événements Git. Offre : l'API, les événements Git et le streaming nécessitent Enterprise Cloud. Adresses IP : masquées, sauf si un propriétaire active leur affichage. Contenu : ni contenu de fichiers, ni diffs, aucune trace de la lecture d'un secret par un workflow, aucune trace des lectures de code par utilisateur dans l'interface web. Périmètre : les journaux de sécurité des comptes personnels sont distincts. Avant d'écrire « aucune preuve de compromission », vérifiez chacun de ces points sur l'export que vous avez réellement analysé.
Tout rapport d'enquête doit préciser ce que les preuves pouvaient et ne pouvaient pas montrer. Pour GitHub, cette liste est courte mais importante, et plusieurs éléments dépendent de votre offre et de vos paramètres, pas de l'attaquant.
Rétention
| Données | Rétention | Source |
|---|---|---|
| Événements d'audit d'organisation / d'entreprise | 180 jours | About the audit log for your enterprise |
Événements Git (git.clone, git.fetch, git.push) | 7 jours | même page, ainsi que la page sur le journal d'audit de l'organisation |
| Fenêtre par défaut de l'API | 3 derniers mois, sauf si created est précisé | Référence REST |
| Journal d'audit GraphQL | 90 à 120 jours de données | Reviewing the audit log (Enterprise Cloud) |
| Logs et artefacts Actions | 90 jours par défaut (configurable) | Paramètres de rétention |
| Journal d'audit en streaming | aussi longtemps que votre stockage le conserve | votre bucket / SIEM |
Concrètement : une intrusion découverte avec trois semaines de retard n'aura aucune trace de clonage, sauf si vous faites du streaming. Une intrusion découverte avec sept mois de retard n'aura presque plus aucune preuve côté GitHub. Le streaming du journal d'audit est le seul moyen de dépasser ces deux limites.
Prérequis selon l'offre
| Fonctionnalité | Free / Team | Enterprise Cloud |
|---|---|---|
| Consulter et exporter le journal d'audit de l'organisation (interface, JSON / CSV) | oui | oui |
| API REST et GraphQL du journal d'audit | non | oui |
| Événements Git | non | oui (API, export, streaming) |
| Streaming du journal d'audit | non | oui (entreprise) |
| Liste d'IP autorisées, SSO SAML | non | oui |
GitHub indique que l'API du journal d'audit nécessite Enterprise Cloud, et il en va de même pour les listes d'IP autorisées. Avec Free et Team, l'export depuis l'interface est votre source principale, et un clonage massif ne peut être déduit qu'indirectement (voir exfiltration de dépôts).
Les paramètres qui changent ce que vous obtenez
- Adresses IP. Par défaut, GitHub n'affiche pas les adresses IP sources. Lorsqu'un propriétaire active leur affichage, cela s'applique aux nouveaux événements comme aux événements existants. Même dans ce cas, les adresses IP ne sont affichées que sous conditions : membres de l'organisation agissant sur des ressources privées ou internes de l'organisation, et requêtes API ayant un contexte de dépôt. Attendez-vous à des trous.
- Métadonnées des jetons.
hashed_token,programmatic_access_typeettoken_scopessont enregistrés pour les événements authentifiés par jeton. Les données concernant les événements Git ainsi que les clés SSH et de déploiement sont indiquées comme étant en préversion publique dans la documentation GitHub, et les recherches parhashed_tokendans l'interface et l'API excluent les événements Git.
Ce qui n'est pas enregistré
- Le contenu des fichiers et les diffs. Le journal d'audit vous dit qu'un push a eu lieu et qu'un workflow s'est exécuté. Il ne vous dit pas ce que contenait le fichier de workflow. Un workflow modifié doit être déduit de ses exécutions (nouvelle branche, secrets affichés) et confirmé dans l'historique du dépôt.
- La lecture des secrets. La création, la modification et la suppression de secrets Actions sont des événements. L'utilisation d'un secret par un workflow pendant une exécution n'en est pas un. L'archive des logs d'exécution est la seule trace de ce qu'une étape en a fait (voir fuite de secrets Actions).
- Les opérations Git effectuées via le web ou l'API. Les événements Git les excluent. Une pull request fusionnée dans le navigateur pousse sur la branche de base sans générer d'événement
git.push. - La consultation du code dans l'interface web. Afficher des fichiers dans le navigateur ne produit pas d'événement d'audit par fichier. Les téléchargements d'archives (
repo.download_zip), si. - Ce qui se passe sur les runners. Le journal d'audit voit l'enregistrement et l'état des runners, pas les commandes qu'un job a exécutées sur un hôte auto-hébergé. Celles-ci se trouvent dans les logs
_diagdu runner (voir sécurité des runners auto-hébergés). - L'activité des comptes personnels. Le journal de sécurité propre à chaque utilisateur (connexions, modifications de 2FA, ses clés SSH et ses jetons) est distinct du journal d'audit de l'organisation et ne fait pas partie de son export. L'utilisateur le consulte lui-même, et l'analyseur ne le lit pas.
- Tout ce qui se passe une fois que l'attaquant a quitté GitHub. Les clés cloud utilisées dans AWS, Google Cloud ou Azure apparaissent dans ces logs-là (voir le pivot cloud).
Les limites de l'analyseur lui-même
L'outil hérite de toutes les lacunes ci-dessus et y ajoute les siennes :
- Heuristiques et seuils. Le clonage massif se déclenche à partir de 10 dépôts distincts par acteur et par adresse IP en une heure environ. Les règles « nouvelle adresse IP » et « nouveau pays » nécessitent 24 heures d'historique par jeton ou par acteur. Un attaquant lent, ou un export qui commence le jour de l'intrusion, peut rester sous ces seuils.
- Des règles de faible gravité bruyantes.
workflow-new-branch,token-new-ipetactions-secret-createdse déclenchent sur du travail normal, par conception. Lisez-les dans leur contexte. - Pas d'enrichissement. Ni recherche d'ASN ou d'hébergeur, ni threat intelligence. Tout reste ainsi hors ligne, mais c'est à vous de juger les adresses IP.
- Plafond de la table. La table des événements liste les 100 000 premiers événements. Tous les événements sont analysés, et les notes de couverture signalent quand la table est tronquée.
- Le verdict « Aucun signe de compromission » signifie « aucune règle ne s'est déclenchée sur ces journaux », pas « aucune compromission ». Les notes de couverture vous indiquent quelles règles étaient aveugles.
Faciliter la prochaine enquête
- Diffusez le journal d'audit en streaming vers un stockage que vous contrôlez, avec une rétention supérieure à 180 jours.
- Activez l'affichage des adresses IP.
- Réglez la rétention des logs Actions pour couvrir votre délai de détection, et transférez les logs des runners auto-hébergés.
- Exportez et archivez les événements Git dès le moindre soupçon. Sept jours passent vite.
- Conservez un export de référence mensuel, pour que la règle « nouveau pays » dispose d'un historique de comparaison.
FAQ
Combien de temps GitHub conserve-t-il le journal d'audit ?
Les événements d'audit d'organisation et d'entreprise sont consultables sur les 180 derniers jours. Les événements Git sont conservés sept jours. Par défaut, l'API renvoie les trois derniers mois, sauf si vous ajoutez un qualificateur created. Le streaming vers votre propre stockage est le moyen d'en conserver davantage.
Le journal d'audit GitHub est-il disponible avec les offres Free et Team ?
Les propriétaires d'organisation peuvent consulter et exporter le journal d'audit de l'organisation depuis l'interface web, quelle que soit l'offre. Les API REST et GraphQL du journal d'audit, les événements Git, le streaming du journal d'audit, les listes d'IP autorisées et le SSO SAML nécessitent GitHub Enterprise Cloud.