Описание
Tekton Pipeline: Git Resolver Unsanitized Revision Parameter Enables git Argument Injection Leading to RCE
Summary
The git resolver's revision parameter is passed directly as a positional argument to git fetch without any validation that it does not begin with a - character. Because git parses flags from mixed positional arguments, an attacker can inject arbitrary git fetch flags such as --upload-pack=<binary>. Combined with the validateRepoURL function explicitly permitting URLs that begin with / (local filesystem paths), a tenant who can submit ResolutionRequest objects can chain these two behaviors to execute an arbitrary binary on the resolver pod. The tekton-pipelines-resolvers ServiceAccount holds cluster-wide get/list/watch on all Secrets, so code execution on the resolver pod enables full cluster-wide secret exfiltration.
Details
Root Cause 1 — Unvalidated revision parameter passed to git fetch
pkg/resolution/resolver/git/repository.go:85:
execGit invokes exec.CommandContext("git", ...) — no shell is used, so shell metacharacters cannot be injected. However, git itself parses flags from mixed positional arguments. When revision = "--upload-pack=/path/to/binary", git receives this as the flag --upload-pack=/path/to/binary, not as a refspec. PopulateDefaultParams (resolver.go:418–424) applies only a leading-slash strip and a containsDotDot check on the pathInRepo parameter; the revision parameter receives no validation at all.
Root Cause 2 — validateRepoURL explicitly permits local filesystem paths
pkg/resolution/resolver/git/resolver.go:154-158:
Any URL beginning with / passes validation and is used directly as the argument to git clone. This means a local filesystem path such as /tmp/some-repo is a valid resolver URL.
Exploit Chain
--upload-pack=<binary> causes git to execute the specified binary as the upload-pack server when communicating with the remote. For local-path remotes (/path), git invokes the binary on the resolver pod itself with the repository path as its sole argument. Because the argument is passed via exec.Command as a single --upload-pack=<binary> string (not split by a shell), only binaries at known paths can be invoked — but several useful binaries exist in the resolver pod image (e.g., /bin/sh, /usr/bin/curl, /bin/cp).
Attack complexity is High because the exploit requires either:
- A valid git repository at a known, predicable path on the resolver pod (e.g.,
/tmp/<reponame>-<suffix>from a concurrent resolution), or - A default-URL configuration pointing at a local path
PoC
Verified: git fetch origin --upload-pack=/tmp/test-exec.sh --depth=1 executes test-exec.sh on the local machine even when origin is a local filesystem path. Exit code 0 was observed with the test binary executed successfully.
Impact
- Code execution on the resolver pod when an attacker can stage or predict a valid git repository path in
/tmpon the resolver pod. - Full cluster-wide Secret exfiltration: The
tekton-pipelines-resolversServiceAccount is bound to a ClusterRole that grantsget/list/watchon all Secrets in all namespaces (config/resolvers/200-clusterrole.yaml). Code execution on the resolver pod is therefore equivalent to reading every Secret in the cluster. - Privilege escalation: Secrets typically include kubeconfig files, cloud provider credentials, and API tokens — reading them enables lateral movement to cloud infrastructure.
- Both the deprecated resolver (
pkg/resolution/resolver/git/) and the current resolver (pkg/remoteresolution/resolver/git/) share the samevalidateRepoURL,PopulateDefaultParams, andcheckoutimplementation via the sharedgitpackage. Both are affected.
Recommended Fix
Fix 1 — Validate that revision does not begin with - in PopulateDefaultParams:
Fix 2 — Restrict validateRepoURL to remote URLs only (remove local-path support in production builds, or add an explicit admin opt-in feature flag):
Applying Fix 1 alone is sufficient to prevent the argument injection. Fix 2 eliminates the enabling condition (local-path remotes for which --upload-pack runs locally) and reduces attack surface further.
Ссылки
- https://github.com/tektoncd/pipeline/security/advisories/GHSA-94jr-7pqp-xhcq
- https://nvd.nist.gov/vuln/detail/CVE-2026-40938
- https://access.redhat.com/errata/RHSA-2026:17546
- https://access.redhat.com/errata/RHSA-2026:24359
- https://access.redhat.com/errata/RHSA-2026:24484
- https://access.redhat.com/errata/RHSA-2026:26519
- https://access.redhat.com/errata/RHSA-2026:26538
- https://access.redhat.com/security/cve/CVE-2026-40938
- https://bugzilla.redhat.com/show_bug.cgi?id=2460292
- https://github.com/tektoncd/pipeline/releases/tag/v1.11.1
- https://security.access.redhat.com/data/csaf/v2/vex/2026/cve-2026-40938.json
Пакеты
github.com/tektoncd/pipeline
>= 1.10.0, < 1.11.1
1.11.1
github.com/tektoncd/pipeline
>= 1.7.0, < 1.9.3
1.9.3
github.com/tektoncd/pipeline
>= 1.4.0, < 1.6.2
1.6.2
github.com/tektoncd/pipeline
>= 1.2.0, < 1.3.4
1.3.4
github.com/tektoncd/pipeline
>= 1.0.0, < 1.0.2
1.0.2
Связанные уязвимости
Tekton Pipelines project provides k8s-style resources for declaring CI/CD-style pipelines. Starting in version 1.0.0 and prior to versions 1.0.2, 1.3.4, 1.6.2, 1.9.3, and 1.11.1, the git resolver's revision parameter is passed directly as a positional argument to git fetch without any validation that it does not begin with a - character. Because git parses flags from mixed positional arguments, an attacker can inject arbitrary git fetch flags such as --upload-pack=<binary>. Combined with the validateRepoURL function explicitly permitting URLs that begin with / (local filesystem paths), a tenant who can submit ResolutionRequest objects can chain these two behaviors to execute an arbitrary binary on the resolver pod. The tekton-pipelines-resolvers ServiceAccount holds cluster-wide get/list/watch on all Secrets, so code execution on the resolver pod enables full cluster-wide secret exfiltration. Versions 1.0.2, 1.3.4, 1.6.2, 1.9.3, and 1.11.1 fix the issue.
Tekton Pipelines project provides k8s-style resources for declaring CI/CD-style pipelines. Starting in version 1.0.0 and prior to versions 1.0.2, 1.3.4, 1.6.2, 1.9.3, and 1.11.1, the git resolver's revision parameter is passed directly as a positional argument to git fetch without any validation that it does not begin with a - character. Because git parses flags from mixed positional arguments, an attacker can inject arbitrary git fetch flags such as --upload-pack=<binary>. Combined with the validateRepoURL function explicitly permitting URLs that begin with / (local filesystem paths), a tenant who can submit ResolutionRequest objects can chain these two behaviors to execute an arbitrary binary on the resolver pod. The tekton-pipelines-resolvers ServiceAccount holds cluster-wide get/list/watch on all Secrets, so code execution on the resolver pod enables full cluster-wide secret exfiltration. Versions 1.0.2, 1.3.4, 1.6.2, 1.9.3, and 1.11.1 fix the issue.