Reproduit la CVE-2026-42880, une vulnérabilité critique d'ArgoCD exposant les secrets Kubernetes via ServerSideDiff. Inclut une configuration de laboratoire automatisée, des scripts de déclenchement et un modèle de détection Nuclei pour les tests de sécurité.
Un environnement de laboratoire pour reproduire et détecter CVE-2026-42880, une vulnérabilité critique dans Argo CD où le gestionnaire gRPC ServerSideDiff expose les données Secret Kubernetes aux utilisateurs en lecture seule.
| Champ | Détails |
|---|---|
| ID CVE | CVE-2026-42880 |
| GHSA | GHSA-3v3m-wc6v-x4x3 |
| CVSS | 9.6 (Critique) — AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N |
| Versions affectées | ArgoCD 3.2.0–3.2.10, 3.3.0–3.3.8 |
| Versions corrigées | 3.2.11, 3.3.9+ |
| CWE | CWE-200, CWE-212 |
serverSideDiff() dans le gestionnaire gRPC d'ArgoCD appelle le dry-run SSA de Kubernetes et retourne predictedLive sans appeler hideSecretData(), exposant les valeurs Secret encodées en base64 dans la réponse.
Chemin vulnérable (v3.2.0) :
argocd app diff --server-side-diff
→ Gestionnaire gRPC ServerSideDiff
→ Dry-run SSA Kubernetes (fusionne tous les gestionnaires de champs)
← predictedLive retourné (inclut les données du contrôleur externe)
❌ hideSecretData() NON appelée → valeurs Secret réelles exposées
Chemin corrigé (v3.2.11) :
...même dry-run SSA...
✅ HideSecretData() appelée → valeurs remplacées par ++++
Les trois conditions doivent être satisfaites simultanément :
| # | Condition | Détails |
|---|---|---|
| 1 | Version ArgoCD vulnérable | 3.2.0–3.2.10 ou 3.3.0–3.3.8 |
| 2 | Annotation d'application | argocd.argoproj.io/compare-options: ServerSideDiff=true,IncludeMutationWebhook=true |
| 3 | Gestionnaire de champ externe sur les données Secret | Champs data du Secret possédés par un gestionnaire non-ArgoCD (ex. External Secrets Operator, Helm, kubectl) |
Seul le rôle role:readonly est requis — aucune permission d'écriture n'est nécessaire.
Machine hôte
├── localhost:30080 ──→ Cluster Kind : cve-vuln (ArgoCD v3.2.0 ⚠ VULNÉRABLE)
│ └── ns: production
│ ├── Secret: db-credentials
│ │ metadata → argocd-controller (synchronisé depuis Git)
│ │ data.* → external-controller ⚠ (injecté séparément)
│ └── Secret: api-credentials (même configuration)
│
├── localhost:30081 ──→ Cluster Kind : cve-patched (ArgoCD v3.2.11 ✓ CORRIGÉ)
│ └── (configuration identique — seule la version d'ArgoCD diffère)
│
└── localhost:3010 ──→ Conteneur Docker : cve-lab-gitea
└── dépôt : gitadmin/manifests.git
└── secret.yaml (pas de champ data — condition préalable de la CVE)
Secret db-credentials (namespace: production)
┌──────────────────────────────────────────────────────────────┐
│ metadata.* → argocd-controller (ArgoCD synchronise depuis Git) │
│ data.* → external-controller (injecté par le script de configuration)│
└──────────────────────────────────────────────────────────────┘
Dry-run SSA : Kubernetes fusionne les champs des deux gestionnaires dans predictedLive
→ ArgoCD ne possède PAS data → data n'est pas masquée par ArgoCD
→ v3.2.0 retourne predictedLive sans hideSecretData() → EXPOSÉ
| Outil | Installation |
|---|---|
| kind | brew install kind |
| kubectl | brew install kubectl |
| Docker Desktop | docker.com |
| CLI argocd | brew install argocd |
| nuclei | brew install nuclei |
| curl, jq, git | préinstallé sur macOS ou brew install jq |
Besoins en ressources : 8 Go+ de RAM libre, 15 Go+ d'espace disque libre, ports 30080 / 30081 / 3010 disponibles.
bash scripts/01-setup-vuln.sh
# ou : make setup-vuln
Prend ~10 minutes. Terminé :
══════════════════════════════════════════════════════
Laboratoire ArgoCD vulnérable prêt !
══════════════════════════════════════════════════════
Interface ArgoCD : http://localhost:30080
Mot de passe admin : <généré automatiquement>
Mot de passe viewer : viewerpass123
Fichier de jeton : .vuln-viewer-token
══════════════════════════════════════════════════════
bash scripts/02-setup-patched.sh
# ou : make setup-patched
bash scripts/03-trigger-cve.sh
# ou : make trigger
Sortie attendue — vulnérable (v3.2.0) :
===== /Secret production/db-credentials ======
< db_password: ++++++++ ← état live masqué
---
> db_password: U3VwM3JTM2NyM3REQiFQYXNzIzIwMjY= ← predictedLive EXPOSÉ !
[EXPOSÉ] décodé : Sup3rS3cr3tDB!Pass#2026
⚠ RÉSULTAT : DONNÉES SECRET EXPOSÉES — VULNÉRABLE
Sortie attendue — corrigé (v3.2.11) :
> db_password: ++++++++ ← masqué
✓ RÉSULTAT : aucune donnée non masquée dans predictedLive — CORRIGÉ
# Cluster vulnérable → devrait produire un résultat [critique]
nuclei -t nuclei/CVE-2026-42880.yaml \
-u http://localhost:30080 \
-var username=viewer \
-var password=viewerpass123
# Cluster corrigé → ne devrait produire aucun résultat
nuclei -t nuclei/CVE-2026-42880.yaml \
-u http://localhost:30081 \
-var username=viewer \
-var password=viewerpass123
bash scripts/99-teardown.sh
# ou : make teardown
argocd-cve-2026-42880-lab2/
├── README.md
├── LAB_SETUP_GUIDE.md # Guide de configuration du lab + dépannage (anglais)
├── VULNERABILITY_ANALYSIS.md # Analyse de vulnérabilité au niveau du code (anglais)
├── Nuclei_Template_Report.md # Conception du template Nuclei et résultats de test (anglais)
├── Makefile
│
├── REPORT/ # Rapports en coréen
│ ├── LAB_REPORT_KR.md
│ ├── Nuclei_Template_Report_KR.md
│ └── Vulnerability_Analysis_KR.md
│
├── kind/
│ ├── cluster-vuln.yaml # Cluster Kind : cve-vuln (port 30080)
│ └── cluster-patched.yaml # Cluster Kind : cve-patched (port 30081)
│
├── git-manifests/
│ └── secret.yaml # Secret sans champ data (condition préalable de la CVE)
│
├── manifests/
│ ├── application.yaml # Application ArgoCD avec annotation vulnérable
│ ├── argocd-cm-patch.yaml # ConfigMap : TLS désactivé, compte viewer, ServerSideDiff
│ ├── argocd-rbac-patch.yaml # RBAC : viewer → role:readonly
│ ├── argocd-nodeport.yaml # NodePort 30080 (cluster vulnérable)
│ └── argocd-nodeport-patched.yaml# NodePort 30081 (cluster corrigé)
│
├── nuclei/
│ └── CVE-2026-42880.yaml # Template de détection Nuclei
│
└── scripts/
├── 01-setup-vuln.sh # Configuration automatisée complète : environnement vulnérable
├── 02-setup-patched.sh # Configuration automatisée complète : environnement corrigé
├── 03-trigger-cve.sh # Déclencher la CVE + comparer les deux clusters
└── 99-teardown.sh # Supprimer toutes les ressources du laboratoire
Le template utilise une chaîne HTTP en 4 étapes pour vérifier toutes les conditions préalables de la CVE sans déclencher l'extraction réelle des Secrets :
Étape 1 GET /api/version
→ extraire argocd_version (aucune authentification requise)