
Gitea avant 1.27.1 permet l'exécution de code à distance via l'API diffpatch par l'installation de hooks Git.
[!WARNING] Ce dépôt est destiné exclusivement à la recherche en sécurité autorisée et aux tests contrôlés en laboratoire. N'exécutez pas la preuve de concept contre des systèmes que vous ne possédez pas ou pour lesquels vous ne disposez pas d'une autorisation explicite d'évaluation.
CVE-2026-60004 est une vulnérabilité critique d'exécution de code à distance dans l'API diffpatch de Gitea. Un utilisateur authentifié disposant de la permission de créer ou d'écrire dans un dépôt peut soumettre un patch conçu pour provoquer la matérialisation d'un hook Git exécutable à l'intérieur d'un dépôt nu temporaire. Lorsque le hook est déclenché, les commandes contrôlées par l'attaquant s'exécutent avec les privilèges du compte de service Gitea.
Si l'inscription publique est activée, un attaquant non authentifié peut être en mesure de créer un compte et d'atteindre le point de terminaison authentifié vulnérable.
| Attribut | Détails |
|---|
| Identifiant | CVE-2026-60004 |
| Avis | GHSA-rcr6-4jqh-j84m |
| Sévérité | Critique — CVSS 3.1 : 9.8 |
| Faiblesse | CWE-94 : Contrôle inapproprié de la génération de code |
| Versions affectées | Gitea 1.17.0 à 1.27.0 |
| Version corrigée | Gitea 1.27.1 |
| Accès requis | Accès en écriture au dépôt |
| Contexte d'exécution | Compte système d'exploitation Gitea |
| Date CISA KEV | 2026-08-25 |
| Fichier | Description |
|---|---|
gitea_diffpatch_rce.py | Preuve de concept utilisant uniquement la bibliothèque standard qui s'authentifie, crée un dépôt privé, soumet le patch conçu et récupère la sortie de commande. |
payload.patch | Exemple de patch qui crée un hook exécutable hooks/post-index-change. |
poc.png | Capture d'écran réalisée lors de la validation en laboratoire. |
README.md | Notes de recherche originales. |
La preuve de concept a été validée dans l'environnement isolé suivant :
| Composant | Configuration |
|---|---|
| Gitea | 1.27.0 |
| Git | 2.47.2 |
| Déploiement | Conteneur Docker nommé gitea-lab |
| Adresse du service | 192.168.184.128:3000 |
| Identité observée | uid=1000(git) gid=1000(git) |
Une exploitation réussie a produit une sortie de commande similaire à :
uid=1000(git) gid=1000(git) groups=1000(git)
Linux 6.12.20-amd64 x86_64
/data/gitea/tmp/local-repo/upload.git630501597
[exit-status=0]

Le script utilise uniquement la bibliothèque standard de Python et ne nécessite aucun paquet supplémentaire.
python3 gitea_diffpatch_rce.py <base_url> <username> <password> "<command>"
Exemple pour une instance de laboratoire locale :
python3 gitea_diffpatch_rce.py \
http://127.0.0.1:3000 \
pocuser \
'P@ssw0rd!' \
'id; uname -a'
Le script tente d'abord une inscription web, puis s'authentifie avec les identifiants fournis. Cela permet à la même commande de fonctionner soit avec un nouveau compte sur une instance avec inscription ouverte, soit avec un compte existant.
La chaîne d'exploitation se compose de quatre étapes :
Soumission d'un patch contrôlé par l'attaquant
POST /api/v1/repos/{owner}/{repo}/diffpatch applique le contenu du patch fourni
à l'aide de git apply --index --recount --cached --binary --ignore-whitespace --whitespace=fix -3 dans un clone temporaire.
Placement du chemin du hook
Le dépôt temporaire est créé en tant que clone nu et partagé. Dans un dépôt
nu, la racine du dépôt est également $GIT_DIR ; par conséquent, le chemin du patch
hooks/post-index-change se résout à l'intérieur du répertoire de hooks actif de Git.
Matérialisation du hook exécutable
Le même patch est soumis deux fois. La seconde application produit un
conflit add/add, provoquant la matérialisation du chemin sur le disque par le repli three-way
avec le mode 100755, malgré l'utilisation de --cached. Une mise à jour ultérieure de l'index
invoque post-index-change, exécutant le code shell injecté en tant que
compte de service Gitea.
Récupération de la sortie native à Git
Le hook identifie le dépôt d'origine via
objects/info/alternates, stocke la sortie de commande en tant que blob Git, crée une
arborescence et un commit, et met à jour refs/heads/output-leak. La preuve de concept
récupère ensuite le résultat via l'API de fichiers bruts de Gitea. Cette technique ne
nécessite pas de connexion sortante directe depuis la cible.
Une exploitation réussie accorde l'exécution de commandes avec les privilèges du compte de service Gitea. Selon la configuration du déploiement, un attaquant peut être en mesure d'accéder à :
app.ini et aux identifiants de base de donnéesSECRET_KEY, INTERNAL_TOKEN et aux secrets liés à LFSIl a été confirmé que le compte de laboratoire disposait d'un accès en lecture à app.ini.
Les défenseurs doivent examiner les artefacts et les schémas de requêtes suivants :
/api/v1/repos/*/*/diffpatch en succession rapideoutput-leakpoc <[email protected]>hooks/post-index-change dans des dépôts
nus ou des répertoires de clone temporaires/data/gitea/tmp/local-repo/upload.git*Ces indicateurs décrivent la preuve de concept incluse et ne sont pas exhaustifs ; un exploit modifié peut utiliser des chemins, des refs, des identités ou des canaux de sortie différents.
/api/v1/.../diffpatch correspondantes. Validez la règle par rapport aux intégrations légitimes avant le déploiement.DISABLE_REGISTRATION=true si elle
n'est pas opérationnellement requise. Cela réduit l'accessibilité non authentifiée mais
ne protège pas contre les utilisateurs existants disposant d'un accès en écriture au dépôt.Pour le conteneur de laboratoire utilisé dans cette recherche, le démontage peut être effectué avec :
docker rm -f gitea-lab
Ce matériel est fourni pour aider les défenseurs à reproduire, comprendre, détecter et remédier à la vulnérabilité. Les opérateurs ne doivent tester que dans des environnements isolés et respecter les exigences d'autorisation et de divulgation de leur organisation.