Rapport CTI technique du 30 juillet 2026
Résumé exécutif
Gitea, la plateforme Git self-hosted utilisée par de nombreuses équipes DevOps comme alternative légère à GitLab ou GitHub Enterprise, a corrigé le 27 juillet 2026 une vulnérabilité critique de confusion de dépôt permettant à n'importe quel titulaire d'un accès en écriture sur un dépôt de planter un hook Git exécutable et de faire tourner des commandes shell avec les privilèges du compte de service Gitea. Tracée CVE-2026-60004 et notée CVSS 9.8, la faille touche toutes les versions 1.17 à 1.27.0. Le point le plus préoccupant pour les défenseurs : la configuration par défaut de Gitea laisse l'inscription ouverte, sans validation d'e-mail ni approbation manuelle, ce qui permet à un visiteur externe sans aucun compte préexistant de créer un compte, un dépôt privé, et de déclencher l'exploitation en quelques requêtes API, sans callback sortant nécessaire.
Techniquement, le bug exploite une confusion entre clone bare et non-bare lors de l'application d'un patch sur l'endpoint POST /api/v1/repos/{owner}/{repo}/diffpatch. En soumettant deux fois le même patch pour provoquer une collision add/add, l'attaquant force le mécanisme de fallback à trois voies de Git (git apply -3) à écrire un fichier dans le répertoire hooks/ du dépôt temporaire, qui se trouve être la racine $GIT_DIR puisque le clone est bare. Git exécute ensuite ce hook automatiquement lors de la mise à jour de l'index. Un correctif public existe depuis la version 1.27.1, avec un PoC déjà en circulation, ce qui place toute instance Gitea non patchée avec inscription ouverte dans une fenêtre de risque immédiate.
Chronologie
| Date | Événement |
|---|---|
| Avant le 26 juillet 2026 | Le chercheur Shai Rod (NightRang3r) prévisualise sur X la RCE ainsi qu'une faille distincte de file inclusion sur Gitea 1.27.0 |
| 26 juillet 2026 | Le correctif (passage du clone temporaire de bare à non-bare) est mergé et backporté |
| 27 juillet 2026 | Gitea publie la version 1.27.1 ; les instances Gitea Cloud sont mises à jour automatiquement |
| 28 juillet 2026 | Publication de l'avis de sécurité officiel GHSA-rcr6-4jqh-j84m avec CVE-2026-60004 et PoC |
| 29 juillet 2026 | Couverture large par The Hacker News et reprises sectorielles |
Fiche vulnérabilité
CVE-2026-60004 | CVSS 3.1 : 9.8 (Critique) | Gitea, versions 1.17 et ultérieures, avant 1.27.1
Description technique : l'endpoint POST /api/v1/repos/{owner}/{repo}/diffpatch applique un patch fourni par l'utilisateur à l'intérieur d'un clone bare temporaire partagé. Les versions vulnérables invoquent git apply avec les options --index, --recount, --cached et --binary, en ajoutant l'option de fallback à trois voies -3 lorsque le serveur tourne sous Git 2.32 ou supérieur. En soumettant deux fois le même patch, l'attaquant crée une collision add/add ; le fallback à trois voies procède alors à un checkout du chemin indexé bien que l'opération utilise --cached. Le clone étant bare, sa racine correspond à $GIT_DIR, si bien qu'un fichier exécutable placé à hooks/post-index-change atterrit directement dans le répertoire de hooks Git et devient actif. Git exécute ce hook lors de la mise à jour de l'index suivante.
Conditions d'exploitation : authentification requise (mais obtenable via l'inscription ouverte par défaut), accès en écriture sur un dépôt (également obtenable en créant son propre dépôt), Git 2.32 ou supérieur côté serveur, route diffpatch activée, et système de fichiers temporaire accessible en écriture et en exécution. Aucun de ces prérequis ne constitue un obstacle réel sur une installation Gitea par défaut.
PoC disponible : oui, publié par le chercheur NightRang3r et référencé dans l'avis GHSA-rcr6-4jqh-j84m. Le PoC se connecte avec un compte ordinaire, crée un dépôt privé initialisé, envoie le patch malveillant deux fois, et récupère la sortie de la commande exécutée sans callback réseau sortant : le hook stocke la sortie dans des objets Git, crée une branche contenant le résultat, et l'attaquant la récupère via HTTP intelligent authentifié.
Patch/mitigation : mise à jour vers Gitea 1.27.1, qui change le clone temporaire de bare à non-bare (le commentaire de code du correctif avertit explicitement que les commandes Git utilisant --index peuvent opérer sur l'arbre de travail). Note importante : le changelog liste cette correction sous « refactor: git patch apply » dans la section divers, pas dans la section sécurité, ce qui augmente le risque qu'elle passe inaperçue lors d'une revue de changelog rapide. La désactivation de l'inscription ouverte réduit la surface d'attaque externe mais ne corrige pas la faille pour les comptes existants disposant d'un accès en écriture.
Diagramme de la chaîne d'attaque

Séquence d'exploitation de la confusion bare/non-bare sur l'endpoint diffpatch de Gitea, reconstituée à partir de l'avis GHSA-rcr6-4jqh-j84m et de la couverture The Hacker News du 29 juillet 2026.
Analyse technique
Étape 1 : obtention d'un compte et d'un accès en écriture
Sur une installation Gitea par défaut, l'inscription est ouverte, ne requiert ni validation d'e-mail ni approbation manuelle, et n'impose aucune restriction sur le nombre de dépôts créés. Un attaquant externe crée donc un compte ordinaire puis un dépôt privé initialisé, obtenant l'accès en écriture nécessaire sans avoir eu besoin d'identifiants préexistants.
Étape 2 : construction du patch malveillant
L'attaquant prépare un patch dont le contenu, une fois appliqué, correspond à un fichier exécutable destiné à hooks/post-index-change. Le contenu du hook peut être une commande shell arbitraire.
Étape 3 : déclenchement de la collision add/add via l'endpoint diffpatch
L'attaquant envoie ce même patch deux fois à POST /api/v1/repos/{owner}/{repo}/diffpatch. La première application ajoute le fichier ; la seconde crée un conflit add/add que Git tente de résoudre via le mécanisme de fallback à trois voies activé par l'option -3 (disponible dès Git 2.32).
Étape 4 : écriture hors du périmètre attendu grâce à la confusion bare/non-bare
Le fallback à trois voies effectue un checkout du chemin indexé malgré l'utilisation de --cached, qui aurait dû limiter l'opération à l'index sans toucher au système de fichiers. Comme le clone temporaire est bare, sa racine correspond directement à $GIT_DIR : le fichier atterrit dans le vrai répertoire hooks/ de ce dépôt Git, et non dans un simple répertoire de travail isolé.
Étape 5 : exécution du hook et exfiltration du résultat sans callback
Lors de la mise à jour d'index suivante, Git exécute automatiquement le hook post-index-change avec les privilèges du compte de service Gitea. Le résultat de la commande est stocké dans des objets Git internes au dépôt, exposés via une branche que l'attaquant récupère simplement en clonant ou en fetchant le dépôt par HTTP authentifié, sans jamais avoir besoin d'une connexion sortante contrôlée par l'attaquant.
Indicateurs de compromission
| Type | Valeur |
|---|---|
| Endpoint ciblé | POST /api/v1/repos/{owner}/{repo}/diffpatch |
| Fichier hook suspect | hooks/post-index-change dans un dépôt Git bare temporaire ou permanent |
| Comportement anormal | Deux soumissions consécutives d'un patch identique provoquant une collision add/add sur le même chemin |
| Version serveur à risque | Git ≥ 2.32 combiné à Gitea 1.17 jusqu'à 1.27.0 |
| Artefact de commit correctif | 470d34b1de87d901bd9135564d5ee18c0d339e82 (passage bare → non-bare) |
MITRE ATT&CK
| Tactique | Technique | ID | Justification |
|---|---|---|---|
| Initial Access | Exploit Public-Facing Application | T1190 | L'endpoint API diffpatch exposé publiquement constitue le vecteur d'entrée |
| Initial Access | Valid Accounts | T1078 | L'inscription ouverte par défaut permet d'obtenir un compte légitime sans identifiants préexistants |
| Execution | Command and Scripting Interpreter: Unix Shell | T1059.004 | Le hook Git planté exécute des commandes shell arbitraires sous l'identité du service Gitea |
| Persistence | Event Triggered Execution | T1546 | Le hook post-index-change s'exécute automatiquement à chaque mise à jour d'index, offrant un mécanisme de déclenchement récurrent tant qu'il reste en place |
| Exfiltration | Exfiltration Over Web Service | T1567 | Le résultat de la commande est récupéré via le protocole Git/HTTP standard du service compromis lui-même |
Aucune cartographie ATT&CK officielle n'a été publiée par Gitea ou par un éditeur tiers pour cette CVE : le tableau ci-dessus est notre lecture technique de la chaîne décrite dans l'avis GHSA.
Remédiation : checklist opérationnelle
- Mettre à jour toute instance Gitea self-hosted vers la version 1.27.1 ou supérieure sans délai.
- Vérifier que les instances Gitea Cloud ont bien reçu la mise à jour automatique annoncée le 27 juillet.
- En attendant la mise à jour, désactiver l'inscription publique (DISABLE_REGISTRATION) pour fermer le vecteur d'accès externe sans identifiants, en gardant à l'esprit que cela ne protège pas contre les comptes internes déjà disposant d'un accès en écriture.
- Auditer les journaux applicatifs Gitea pour repérer des appels répétés à POST /api/v1/repos/{owner}/{repo}/diffpatch avec un contenu de patch identique sur une courte fenêtre de temps.
- Inspecter les dépôts existants pour la présence de fichiers exécutables inattendus sous hooks/, en particulier post-index-change.
- Passer en revue les comptes créés récemment sans validation d'e-mail ni activité légitime associée, en particulier ceux ayant créé des dépôts privés puis effectué des opérations de patch inhabituelles.
- Isoler le compte de service Gitea avec le principe du moindre privilège (accès filesystem restreint, pas d'accès direct aux secrets applicatifs ou à la base de données) pour limiter l'impact d'une exécution de commande réussie.
- Surveiller les mises à jour du changelog Gitea au-delà de la seule section « Security », comme l'illustre ce correctif classé sous « Misc ».