GHSA-94jr-7pqp-xhcq: Tekton Pipeline: Git Resolver Unsanitized Revision Parameter Enables git Argument Injection Leading to RCE
SummaryThe 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.DetailsRoot 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), orA default-URL configuration pointing at a local pathPoC**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 `/tmp` on the resolver pod.**Full cluster-wide Secret exfiltration**: The `tekton-pipelines-resolvers` ServiceAccount is bound to a ClusterRole that grants `get/list/watch` on 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 same `validateRepoURL`, `PopulateDefaultParams`, and `checkout` implementation via the shared `git` package. 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.
CVSS v3.1: 7.5