Exfiltration de dépôts GitHub : détecter le clonage massif
Repérer le vol de code dans le journal d'audit GitHub : rafales de git.clone, archives ZIP, dépôts rendus publics ou transférés, forks, et ce qu'il en reste.
En bref. Le code source quitte GitHub de cinq façons : git.clone/git.fetch, repo.download_zip, passage du dépôt en public (repo.access), transfert (repo.transfer*) ou fork vers un compte personnel. Les deux premières exigent des événements Git ou d'archive ; pour les clones, cela signifie Enterprise Cloud et une fenêtre de conservation de 7 jours. Le schéma à chercher : un acteur ou un jeton qui récupère de nombreux dépôts distincts depuis une même IP en moins d'une heure. Quand vous le voyez, considérez comme fuité chaque secret présent dans l'historique de ces dépôts.
La question « qu'ont-ils emporté ? » vient juste après « comment sont-ils entrés ? ». Elle détermine si vous faites face à une fuite, à une tentative d'extorsion ou à un risque de chaîne d'approvisionnement (le code volé révèle votre infrastructure et contient souvent des identifiants). Le vol de dépôts à grande échelle est un schéma bien réel : en mai 2026, GitHub a lui-même signalé un accès non autorisé à ses dépôts internes, après la compromission du poste d'un employé via une extension VS Code tierce piégée.
Les cinq voies d'exfiltration et leurs traces
| Voie | Action d'audit | Où elle apparaît | Règle de l'analyseur |
|---|---|---|---|
| Clone / fetch via Git | git.clone, git.fetch | Événements Git uniquement (API include=git/all, export de l'entreprise, streaming) | git-clone-burst (élevée) |
| Téléchargement d'archive du code | repo.download_zip | Journal d'audit classique | archive-download-burst (moyenne) |
| Changement de visibilité | repo.access avec visibility: public | Journal d'audit classique | repo-made-public (élevée) |
| Transfert à un autre propriétaire | repo.transfer, repo.transfer_outgoing, repo.transfer_start | Journal d'audit classique | repo-transferred (élevée) |
| Fork vers un compte personnel | politique : private_repository_forking.enable | Journal d'audit classique | private-forking-enabled (faible) |
ATT&CK classe les deux premières sous T1213.003 Data from Information Repositories: Code Repositories. Rendre un dépôt public relève de T1567 Exfiltration Over Web Service, et un transfert de T1537 Transfer Data to Cloud Account.
Clonage massif : lire git.clone
GitHub décrit git.clone comme « un dépôt a été cloné » et précise que l'événement n'est pas disponible dans l'interface web, seulement via l'API REST, le streaming ou les exports. Un événement de clone vous donne l'acteur, le dépôt (repository, repository_public), l'heure, le transport (transport_protocol_name : http ou ssh) et, quand ils sont disponibles, actor_ip, le pays, l'user agent et le hashed_token de l'identifiant utilisé.
À quoi ressemble la normale : un développeur clone une poignée de dépôts sur lesquels il travaille, depuis son IP habituelle, avec son user agent git/2.x habituel. Les systèmes de CI récupèrent sans cesse les mêmes dépôts.
À quoi ressemble un vol :
- Étendue. De nombreux dépôts distincts, dont certains où l'acteur n'a jamais poussé.
- Vitesse. Des clones espacés de quelques secondes : c'est un script, pas une personne.
- Origine. Une IP que l'acteur n'a jamais utilisée, souvent chez un hébergeur, dans un pays nouveau pour le jeton.
- Identifiant. Le même
hashed_tokenque celui du développeur, mais avec un autre user agent.
La règle git-clone-burst de l'analyseur regroupe les git.clone par acteur et par IP et se déclenche à 10 dépôts distincts en 60 minutes. Ce seuil est volontairement prudent. Un nouvel arrivant qui clone le monorepo et ses satellites le premier jour peut le déclencher ; c'est pourquoi le constat liste les dépôts et l'IP, pour que vous puissiez trancher vite.
Quand il n'y a pas d'événements Git
Sans événements Git, l'analyseur le signale dans ses notes de couverture (« la détection du clonage massif est aveugle »). C'est le cas courant sur GitHub Free et Team, où l'API et les événements Git ne sont pas disponibles. Vos options :
- Vérifiez
repo.download_zipdans le journal classique : les téléchargements d'archive y sont consignés. - Consultez la page Traffic du dépôt. Toute personne ayant un accès en écriture y voit les clones complets des 14 derniers jours, en nombres agrégés, sans acteur ni IP. Voir viewing traffic to a repository.
- Considérez comme exposé tout ce que l'identifiant volé pouvait lire. C'est la seule hypothèse défendable.
Téléchargements d'archives
repo.download_zip consigne qu'« une archive du code source d'un dépôt a été téléchargée au format ZIP ». C'est une alternative plus discrète à git clone : pas de client Git, un navigateur ou un user agent curl ordinaire, et une trace dans le journal d'audit classique. archive-download-burst se déclenche à 5 dépôts distincts en une heure pour un même acteur. Les archives ne contiennent pas l'historique Git, ce qui limite un peu le butin : les secrets supprimés dans des commits ultérieurs ne sont pas dans un ZIP de l'arborescence actuelle.
Dépôts rendus publics ou transférés
Ces actions sont bruyantes, mais les attaquants s'en servent pour l'extorsion et pour les opérations « on publie et on disparaît » :
repo.accessavecvisibility: public: du code privé devient téléchargeable par n'importe qui en quelques secondes. Même si vous revenez en arrière très vite, partez du principe qu'il a été copié.repo.transfer_start/repo.transfer/repo.transfer_outgoing: le dépôt, ses issues et son historique passent à un autre propriétaire.repo.destroyen série (trois suppressions ou plus en une heure déclenchentrepo-mass-delete) va souvent de pair avec une demande de rançon. Un dépôt supprimé peut généralement être restauré dans les 90 jours (avec des exceptions pour les réseaux de forks) : vérifiez-le avant toute négociation.
Délimiter : de « cloné » à « exposé »
Une fois la liste des dépôts établie, on passe de la détection à l'impact :
- Exportez la liste (dans l'analyseur : les entités du constat, ou les Événements filtrés sur
git.cloneet l'IP de l'attaquant → Événements CSV). - Analysez l'historique complet de chaque dépôt à la recherche de secrets, y compris les fichiers supprimés et les anciens commits : l'attaquant a l'historique, lui aussi.
- Renouvelez chaque identifiant trouvé, en commençant par les clés cloud et les chaînes de connexion aux bases de données. Pour les clés cloud, poursuivez avec le rebond vers le cloud.
- Recensez la connaissance d'infrastructure. Terraform, charts Helm et modèles de CI décrivent votre réseau à l'attaquant ; évaluez ce qu'ils révèlent.
- Préparez-vous à la divulgation et à l'extorsion. Les décisions juridiques et de communication dépendent de ce que contenait le code (données clients dans des fixtures, code sous licence, composants sensibles pour la sécurité).
Prévenir et détecter plus tôt
- Diffusez le journal d'audit en streaming (Enterprise Cloud) pour que les événements Git survivent à la fenêtre de sept jours. Voir streaming du journal d'audit.
- Activez l'affichage des IP et une liste d'IP autorisées : les clones depuis un VPS échouent alors au lieu de réussir.
- Laissez désactivée la politique de fork des dépôts privés, et alertez sur
private_repository_forking.enable. - Gardez les secrets hors des dépôts : activez le secret scanning et la push protection. L'analyseur signale
secret_scanning_push_protection.bypass.
FAQ
Peut-on savoir qui a cloné mon dépôt GitHub privé ?
Dans une organisation sur GitHub Enterprise Cloud, oui : les événements git.clone enregistrent l'acteur, le dépôt, l'heure et, si l'affichage des IP est activé, l'IP source et l'empreinte du jeton. Ils sont conservés sept jours et ne figurent pas dans l'export de l'interface web. Sur les autres offres, le journal d'audit ne donne pas d'enregistrement par clone.
À lire aussi
- Jeton GitHub fuité : que faire et comment enquêter
- Exporter le journal d'audit GitHub : la section sur les événements Git
- Le cas fictif northwind-labs : 38 dépôts clonés depuis un VPS
- Glossaire : événements Git