The Argo CD Repo-Server Flaw: What to Check If You Run GitOps on AKS
On 1 July 2026 Synacktiv published an unauthenticated remote code execution flaw in Argo CD’s repo-server. Hugo Vincent’s write-up, “Caught in the Octopus Trap”, describes finding it with a custom CodeQL model pack applied to what Synacktiv calls “more than 238,000 lines of code”, and the result is short enough to state in one sentence: the repo-server’s gRPC endpoint on port 8081 does not authenticate its callers, and one of its methods will run a command of your choosing. Synacktiv reported it to the maintainers in January 2025. Eighteen months later there was still no fix and no CVE, so they published. When I went through the upstream repositories and advisories for this post in early October 2026, Argo CD itself still had no release that fixes it. The two CVE IDs that exist by now, CVE-2026-62185 and CVE-2026-15416, both belong to the Helm chart advisory described below. Every version number in this post reflects that date.
This pattern, GitOps via CI driving a Helm sync into a managed Kubernetes cluster, is a common setup.
The chain, briefly
Synacktiv tested Argo CD v2.13.3 and did not publish a full list of affected versions. The chain they describe starts with a pod that can reach argocd-repo-server on port 8081 and calls /repository.RepoServerService/GenerateManifest. There is no token, no mTLS, and nothing else that checks identity either. The request carries Kustomize build options, and --enable-helm --helm-command ./exfil.sh is enough to make Kustomize execute an attacker-supplied script where it would otherwise execute Helm. That script reads REDIS_PASSWORD out of the repo-server pod’s environment. With the password, the attacker writes to Argo CD’s Redis cache: the mfst manifest entries, and the git-refs entries holding commit hashes, which is what convinces the application controller that something changed upstream. Auto-sync then applies the poisoned manifest with the Argo CD service account’s privileges, a step Control Plane spelled out in their 6 July 2026 analysis of the same flaw. Control Plane, a Kubernetes security consultancy, published the most operationally useful mitigation list on this so far.
The first half of that chain is a command injection bug, the kind that gets fixed in a point release once somebody finds it. The second half is the part I would still think about if the first half were patched tomorrow, because the problem sits in a design decision: Argo CD’s cache is a trusted input to the one component in the cluster with permission to change everything. CVE-2024-31989, scored 9.0 and fixed in 2.8.19, 2.9.15, 2.10.10 and 2.11.1, had the same shape: reach Redis on 6379 from any pod and the cache rewrite gives you the deployments. Argo CD’s own security documentation still states that “Communication with Redis is performed over plain HTTP by default. TLS can be setup with command line arguments.”
The same page says “The repo-server does not carry any Kubernetes privileges and does not store credentials to any services (including git).” Both sentences are true, and neither helps, because the privilege the attacker wants is held by the controller downstream of the cache, and the credential they need is the cache password sitting in the pod’s environment.
The Helm chart half, which does have a CVE
Advisory GHSA-47m3-95c7-g2g8, published 29 June 2026 against argoproj/argo-helm, puts it plainly: “Argo CD by default restricts network access to repo server and other components but the Helm package by default does not.” The advisory is rated high at CVSS 8.9 on its own 3.1 vector. A CVE was assigned later, CVE-2026-62185 (Red Hat tracks the same advisory as CVE-2026-15416), which OSV published on 13 July 2026 with 8.6 under CVSS 4.0 and the summary “Argo CD Helm Chart < 10.0.0 Missing Network Policy RCE”. The fix landed in Argo CD Helm chart 10.0.0, which flipped global.networkPolicy.create from false to true.
If you deployed Argo CD with the chart before 10.0.0 and never overrode that value, you have been running the upstream security model minus its network isolation, and the repo-server has been reachable from any pod in the cluster the whole time.
Upgrading the chart is necessary but it is not the end of the checklist. Here is the relevant block from the chart’s current values.yaml, at chart version 10.9.6 with app version v3.5.3:
networkPolicy:
# -- Create NetworkPolicy objects for all components
create: true
# -- Default deny all ingress traffic
defaultDenyIngress: false
Policies get created now. A namespace-wide default deny does not. The per-component policy the chart generates for the repo-server selects the repo-server pods and allows ingress on the repo-server port from Argo CD’s own components only: argocd-server, the application controller, the ApplicationSet controller, and the notifications controller when that is switched on. That is the right rule. It also opens the metrics port to namespaceSelector: {}, meaning every namespace, which is a reasonable trade for scrape access, and the kind of thing better learned from the chart than from an audit finding.
On AKS, a NetworkPolicy is not self-enforcing
This is the part I would check first on an AKS cluster, because it is the failure mode where everything looks correct.
Microsoft’s AKS documentation is direct about the starting point: “By default, all pods in an AKS cluster can send and receive traffic without limitations.” Enforcement requires a policy engine, and Azure offers three: Cilium for clusters on Azure CNI Powered by Cilium, Azure Network Policy Manager, and Calico. Microsoft recommends Cilium. Without one of them enabled on the cluster, a NetworkPolicy object is accepted by the API server and shows up in kubectl get networkpolicy -A. It just does nothing.
The uninstall note in the same documentation is the sentence to pin to the wall: “The upgrade doesn’t remove any network policy resources in the cluster, but the policies are no longer enforced after the uninstall process.” A cluster can carry a complete, correct set of Argo CD network policies and enforce none of them, with no error anywhere to tell you.
So before kubectl, run az aks show --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME --query "networkProfile" --output table. If networkPolicy is none, the chart’s policies are decoration.
Two practical notes if that check comes back as none. Installing Azure NPM or Calico on an existing cluster triggers every node pool to be reimaged simultaneously, and Microsoft explicitly says upgrading node pools separately is not supported, so this is a maintenance window, not a kubectl apply. And if you are reaching for Azure NPM on Linux nodes, it loses AKS support on 30 September 2028, with a documented migration path to Cilium Network Policy; NPM also does not support scaling beyond 250 nodes and 20,000 pods. Picking Cilium now saves doing this twice.
What network policy does not cover
Network isolation is the mitigation for this particular flaw. It is not the whole blast radius, and the other items on the list are cheaper to fix.
The default AppProject is the one I would look at next. Argo CD’s own user guide describes it as allowing “deployments from any source repo, to any cluster, and all resource Kinds”, with sourceRepos: ['*'], destinations of '*' for both server and namespace, and a clusterResourceWhitelist of group: '*', kind: '*'. The documentation’s own recommendation is unambiguous: “The project is useful for initial testing, but it is recommended to create dedicated projects with explicit source, destination, and resource permissions.” The quickstart puts applications in default, and nothing moves them out later unless somebody decides to.
Redis authentication is the next one. The chart’s redis-ha block ships with auth: true and an existingSecret of argocd-redis; TLS for that connection is not a setting in the block at all, it is controlled separately through Argo CD’s own command-line flags. The password sitting in the repo-server’s pod environment, which step three of the attack chain reads directly, is exactly what the CNCF’s 2023 Argo CD threat model flagged, noting that “including secret information as an environment variable is discouraged, and the Secret should be passed to the pod container as a local file via a volumeMount.” Control Plane’s own mitigation for this part of the chain is to enable TLS between Argo CD and Redis, restrict Secret access in the argocd namespace, and enable etcd encryption at rest. Then there is the sync service account. Control Plane recommend removing cluster-admin from argocd-manager.
Tier zero is a budget decision
CSO Online covered this on 2 July 2026 and quoted the cybersecurity researcher Devashri Datta with the clearest framing of the problem: “Because the repo-server’s gRPC service does not enforce authentication, any pod that can reach it becomes equivalent to an authenticated attacker.” Sakshi Grover, senior research manager for cybersecurity services research at IDC Asia/Pacific, put the follow-up question to leadership in the same piece: “CISOs should therefore evaluate which workloads can communicate with the Argo CD control plane, whether east-west traffic is appropriately segmented, and whether unnecessary trust relationships exist between application workloads and GitOps infrastructure.” The Cloud Security Alliance’s research note of 4 July 2026 adds the uncomfortable extension that Argo CD is increasingly used as the control point for MLOps deployments, which makes a compromised repo-server “a pivot point into every downstream system that a GitOps-managed MLOps pipeline could touch”.
I built a VPC foundation and provisioned hardened machine images for a company-wide AWS migration years before any of this, which is enough exposure to the network layer to recognise what the old chart default encoded: isolation is the control that gets quietly deferred, because deferring it never breaks anything today. Calling the repo-server “internal” was always a description of where its traffic went, not a claim about who could be trusted to reach it, and Argo CD’s upstream manifests have shipped network policies on that basis for years. The chart’s old default just never carried that distinction over.
None of this needs a patch to act on. Confirm the cluster has a policy engine, upgrade the chart past 10.0.0, decide whether you want defaultDenyIngress, move applications off the default project, and look at what argocd-manager is allowed to do. That is an afternoon of work against a flaw for which Synacktiv already have an exploitation tool, argo-cdown, written and for now deliberately held back.
I’m a senior Java architect working on backend platforms, architecture and the quality gates that decide what ships. From January 2027 I’m available for freelance engagements. More about my work on marc-nuetzel.de.
