CVE-2026-47680 Overview
CVE-2026-47680 is a path traversal vulnerability [CWE-23] in the Flux source-controller, a Kubernetes operator that acquires artifacts from Git, OCI, Helm, and S3-compatible sources. Versions 0.0.17 through 1.8.4 allow an actor who controls the contents of a referenced bucket to cause the controller to write fetched object data outside the per-reconciliation working directory. A second surface, introduced in v1.6.0 with sparse-checkout support, lets users with GitRepository create or update rights probe arbitrary paths on the controller pod through resource status feedback.
Critical Impact
Attackers with bucket write access can write files to any location the source-controller pod has permission to write, and users with GitRepository permissions can enumerate file paths on the controller filesystem.
Affected Products
- Flux source-controller versions 0.0.17 through 1.8.4 (bucket path traversal surface)
- Flux source-controller versions 1.6.0 through 1.8.4 (GitRepository sparse-checkout enumeration surface)
- Kubernetes clusters using Flux CD for GitOps reconciliation
Discovery Timeline
- 2026-09-08 - CVE-2026-47680 published to NVD
- 2026-09-09 - Last updated in NVD database
Technical Details for CVE-2026-47680
Vulnerability Analysis
The source-controller fetches remote artifacts and stages them in a per-reconciliation working directory before verification and publication. When resolving object keys from a Bucket resource, the controller joined the working directory with the untrusted object path using filepath.Join, which does not resolve .. segments or symlinks against a bounded root. An adversary who can influence bucket contents can supply keys that traverse out of the working directory, causing writes to arbitrary paths the pod can access.
A distinct surface exists in the sparse-checkout validation path of GitRepository. The validateSparseCheckoutPaths function called filepath.Join(dir, path) and then os.Lstat on the result. Because the result and any error are exposed through the resource status, an authorized user can supply crafted .spec.sparseCheckout entries to determine whether arbitrary filesystem paths exist on the controller pod.
Downstream digest verification in source-controller, kustomize-controller, and helm-controller still prevents a manipulated artifact from reaching workloads, but the write and enumeration primitives on the controller pod remain.
Root Cause
The root cause is the use of filepath.Join on attacker-influenced path components without constraining the result to a trusted base directory. filepath.Join cleans the path but permits .. traversal beyond the intended root, which is the classic pattern for [CWE-23] relative path traversal.
Attack Vector
Exploitation requires either write access to an S3-compatible bucket referenced by a Bucket resource, or Kubernetes RBAC permission to create or update GitRepository resources in a namespace reconciled by Flux. Both are network-reachable via the Kubernetes API or object storage, with low attack complexity and low privileges.
// Patched code in internal/controller/gitrepository_controller.go
func (r *GitRepositoryReconciler) validateSparseCheckoutPaths(obj *sourcev1.GitRepository, dir string) error {
if obj.Spec.SparseCheckout != nil {
for _, path := range obj.Spec.SparseCheckout {
fullPath, err := securejoin.SecureJoin(dir, path)
if err != nil {
return fmt.Errorf("sparse checkout dir '%s' cannot be resolved: %w", path, err)
}
if _, err := os.Lstat(fullPath); err != nil {
return fmt.Errorf("sparse checkout dir '%s' does not exist in repository: %w", path, err)
}
}
}
}
// Source: https://github.com/fluxcd/source-controller/commit/759bd6c451e7cc4327b38f42c8b671980165cb0e
The fix replaces filepath.Join with securejoin.SecureJoin from github.com/cyphar/filepath-securejoin, which resolves symlinks and rejects paths escaping the base directory. The same import and pattern were applied to the bucket reconciler.
Detection Methods for CVE-2026-47680
Indicators of Compromise
- Files appearing outside the source-controller working directory (typically under /tmp or the controller's data volume) that do not match expected artifact staging patterns.
- GitRepository resources whose .spec.sparseCheckout entries contain .. sequences or absolute path prefixes such as /etc or /var.
- Bucket resources referencing storage locations that contain object keys with embedded .. traversal sequences.
Detection Strategies
- Audit Kubernetes API server logs for create and update operations on GitRepository resources and inspect the spec.sparseCheckout field for traversal or absolute path patterns.
- Monitor source-controller pod filesystem writes with runtime workload protection to detect file creation outside expected artifact directories.
- Review GitRepository status conditions for error messages referencing paths outside the cloned repository tree, which indicate enumeration attempts.
Monitoring Recommendations
- Enable Kubernetes audit logging for the source.toolkit.fluxcd.io API group and forward events to a central analytics platform for correlation.
- Alert on source-controller pod restarts, permission errors, or writes to sensitive paths such as /etc, /var/run/secrets, or mounted service account token directories.
- Track the deployed source-controller image tag across clusters to confirm all instances are on v1.8.5 or later.
How to Mitigate CVE-2026-47680
Immediate Actions Required
- Upgrade source-controller to v1.8.5 or later across all Flux installations. This is the only in-product remediation.
- Restrict RBAC on GitRepository and Bucket resources to trusted operators, and remove write access from service accounts that do not require it.
- Review bucket ACLs and IAM policies to ensure only trusted principals can write objects to buckets referenced by Bucket resources.
Patch Information
The vulnerability is fixed in source-controller v1.8.5. The patch, delivered in Pull Request #2054 and commit 759bd6c, replaces unsafe filepath.Join calls with securejoin.SecureJoin in both the bucket and GitRepository reconcilers. Full details are in the GitHub Security Advisory GHSA-jjrm-hr5f-673x.
Workarounds
- Deploy a Kubernetes ValidatingAdmissionPolicy to reject GitRepository resources whose .spec.sparseCheckout entries contain .. or absolute path segments.
- Use a third-party policy engine such as Kyverno or OPA Gatekeeper to enforce equivalent validation for the sparse-checkout surface.
- Constrain the source-controller pod with a read-only root filesystem and minimal writable volumes to reduce the blast radius of arbitrary writes.
# ValidatingAdmissionPolicy to block sparseCheckout traversal
cat <<'EOF' | kubectl apply -f -
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: gitrepository-sparsecheckout-guard
spec:
failurePolicy: Fail
matchConstraints:
resourceRules:
- apiGroups: ["source.toolkit.fluxcd.io"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["gitrepositories"]
validations:
- expression: >-
!has(object.spec.sparseCheckout) ||
object.spec.sparseCheckout.all(p,
!p.contains('..') && !p.startsWith('/'))
message: "sparseCheckout entries must not contain '..' or start with '/'"
EOF
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

