GHSA-RMX9-2PP3-XHCR

Vulnerability from github – Published: 2026-04-21 16:25 – Updated: 2026-05-22 16:05
VLAI
Summary
Tekton Pipelines has VerificationPolicy regex pattern bypass via substring matching
Details

hey guys,

triage contract this is a first-screen summary; deterministic proof is in the proof bundle (canonical.log/control.log/witness.txt).

summary trusted resources verification policies match a resource source string (refSource.URI) against spec.resources[].pattern using regexp.MatchString. in go, regexp.MatchString reports a match if the pattern matches anywhere in the string, so common unanchored patterns (including examples in tekton documentation) can be bypassed by attacker-controlled source strings that contain the trusted pattern as a substring. this can cause an unintended policy match and change which verification mode/keys apply.

pins - repo: https://github.com/tektoncd/pipeline - commit: 0133513db03dadb3cb08801d6b0330badcb63830 - callsite: pkg/trustedresources/verify.go:118-137 (getMatchedPolicies)

severity MEDIUM (provisional CVSS 5.3–6.5) (signing request tampering)

repro (canonical) - command: unzip -q -o poc.zip -d poc && cd poc/poc-F-TEKTON-REGEX-001 && make canonical - expected: cap not reached; canonical does not emit the vulnerability markers. - actual: cap reached; canonical emits the vulnerability markers. - canonical markers (mandatory): [CALLSITE_HIT] + [PROOF_MARKER]

negative control - command: unzip -q -o poc.zip -d poc && cd poc/poc-F-TEKTON-REGEX-001 && make control - expected: cap not reached under the same harness; control emits the control marker and does not emit the vulnerability markers. - control markers (mandatory): [CALLSITE_HIT] + [NC_MARKER]

fix consider making matching safe-by-default by requiring full-string matches (or validating patterns and documenting substring semantics clearly). one option is to anchor patterns before matching (e.g., wrap pattern as ^(?:pattern)$ when not already anchored), or to provide a separate field for exact match vs regex match. fix accepted when: under the same harness, canonical still hits [CALLSITE_HIT] but does not emit [PROOF_MARKER].

proof bundle pointers - bundle: poc.zip - bundle convention: zip extracts under a single top-level folder (poc-F-TEKTON-REGEX-001/) to avoid collisions - contains: canonical.log, control.log, witness.txt - extracted paths: after extraction, see ./poc/poc-F-TEKTON-REGEX-001/canonical.log, ./poc/poc-F-TEKTON-REGEX-001/control.log, ./poc/poc-F-TEKTON-REGEX-001/witness.txt - verify: compare shasum -a 256 for canonical.log/control.log/fix.patch/test source against witness.txt - supported-mode note: if your supported integration uses verified https app-links/universal links only, provide the supported tag/branch and we can retest on that pin.

poc.zip


impact an attacker can craft a trusted resources source string that embeds a trusted substring and still matches an unanchored verificationpolicy spec.resources[].pattern, even if the policy is intended to constrain matches to a specific trusted source. this occurs because regexp.MatchString succeeds on substring matches, so patterns like https://github.com/tektoncd/catalog.git match attacker-controlled sources such as https://evil.com/?x=https://github.com/tektoncd/catalog.git.

affected: deployments using trusted resources verification with unanchored verificationpolicy patterns, where an attacker can influence the refSource.URI value used for policy matching.

not affected: deployments that anchor all patterns (^...$) or otherwise enforce full-string matching; deployments where attackers cannot influence refSource.URI.

steps to reproduce

unzip -q -o poc.zip -d /tmp/poc-tekton-regex-001
cd /tmp/poc-tekton-regex-001/poc-F-TEKTON-REGEX-001
bash ./run.sh canonical | tee /tmp/tekton-regex-001-canonical.log
bash ./run.sh control | tee /tmp/tekton-regex-001-control.log
grep -n '\\[PROOF_MARKER\\]' /tmp/tekton-regex-001-canonical.log && grep -n '\\[NC_MARKER\\]' /tmp/tekton-regex-001-control.log && ! grep -n '\\[PROOF_MARKER\\]' /tmp/tekton-regex-001-control.log

suggested patch options: - make matching safe-by-default by anchoring patterns before matching (or by validating and rejecting unanchored patterns). - document the substring semantics explicitly and update documentation examples to include anchors.

workarounds anchor verificationpolicy resource patterns so they must match the full source string. example:

  • ^https://github.com/tektoncd/catalog\\.git$

best, oleh

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/tektoncd/pipeline"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0.43.0"
            },
            {
              "fixed": "1.0.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/tektoncd/pipeline"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "1.2.0"
            },
            {
              "fixed": "1.3.4"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/tektoncd/pipeline"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "1.4.0"
            },
            {
              "fixed": "1.6.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/tektoncd/pipeline"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "1.7.0"
            },
            {
              "fixed": "1.9.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/tektoncd/pipeline"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "1.10.0"
            },
            {
              "fixed": "1.11.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-25542"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-185"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-04-21T16:25:19Z",
    "nvd_published_at": "2026-04-21T17:16:24Z",
    "severity": "MODERATE"
  },
  "details": "hey guys,\n\ntriage contract\nthis is a first-screen summary; deterministic proof is in the proof bundle (canonical.log/control.log/witness.txt).\n\nsummary\ntrusted resources verification policies match a resource source string (`refSource.URI`) against `spec.resources[].pattern` using `regexp.MatchString`. in go, `regexp.MatchString` reports a match if the pattern matches anywhere in the string, so common unanchored patterns (including examples in tekton documentation) can be bypassed by attacker-controlled source strings that contain the trusted pattern as a substring. this can cause an unintended policy match and change which verification mode/keys apply.\n\npins\n- repo: https://github.com/tektoncd/pipeline\n- commit: 0133513db03dadb3cb08801d6b0330badcb63830\n- callsite: pkg/trustedresources/verify.go:118-137 (getMatchedPolicies)\n\nseverity\nMEDIUM (provisional CVSS 5.3\u20136.5) (signing request tampering)\n\nrepro (canonical)\n- command: unzip -q -o poc.zip -d poc \u0026\u0026 cd poc/poc-F-TEKTON-REGEX-001 \u0026\u0026 make canonical\n- expected: cap not reached; canonical does not emit the vulnerability markers.\n- actual: cap reached; canonical emits the vulnerability markers.\n- canonical markers (mandatory): [CALLSITE\\_HIT] + [PROOF\\_MARKER]\n\nnegative control\n- command: unzip -q -o poc.zip -d poc \u0026\u0026 cd poc/poc-F-TEKTON-REGEX-001 \u0026\u0026 make control\n- expected: cap not reached under the same harness; control emits the control marker and does not emit the vulnerability markers.\n- control markers (mandatory): [CALLSITE\\_HIT] + [NC\\_MARKER]\n\nfix\nconsider making matching safe-by-default by requiring full-string matches (or validating patterns and documenting substring semantics clearly). one option is to anchor patterns before matching (e.g., wrap `pattern` as `^(?:pattern)$` when not already anchored), or to provide a separate field for exact match vs regex match.\nfix accepted when: under the same harness, canonical still hits [CALLSITE\\_HIT] but does not emit [PROOF\\_MARKER].\n\nproof bundle pointers\n- bundle: poc.zip\n- bundle convention: zip extracts under a single top-level folder (poc-F-TEKTON-REGEX-001/) to avoid collisions\n- contains: canonical.log, control.log, witness.txt\n- extracted paths: after extraction, see ./poc/poc-F-TEKTON-REGEX-001/canonical.log, ./poc/poc-F-TEKTON-REGEX-001/control.log, ./poc/poc-F-TEKTON-REGEX-001/witness.txt\n- verify: compare shasum -a 256 for canonical.log/control.log/fix.patch/test source against witness.txt\n- supported-mode note: if your supported integration uses verified https app-links/universal links only, provide the supported tag/branch and we can retest on that pin.\n\n[poc.zip](https://github.com/user-attachments/files/24833926/poc.zip)\n\n---\n\nimpact\nan attacker can craft a trusted resources source string that embeds a trusted substring and still matches an unanchored verificationpolicy `spec.resources[].pattern`, even if the policy is intended to constrain matches to a specific trusted source. this occurs because `regexp.MatchString` succeeds on substring matches, so patterns like `https://github.com/tektoncd/catalog.git` match attacker-controlled sources such as `https://evil.com/?x=https://github.com/tektoncd/catalog.git`.\n\naffected: deployments using trusted resources verification with unanchored verificationpolicy patterns, where an attacker can influence the `refSource.URI` value used for policy matching.\n\nnot affected: deployments that anchor all patterns (`^...$`) or otherwise enforce full-string matching; deployments where attackers cannot influence `refSource.URI`.\n\nsteps to reproduce\n```bash\nunzip -q -o poc.zip -d /tmp/poc-tekton-regex-001\ncd /tmp/poc-tekton-regex-001/poc-F-TEKTON-REGEX-001\nbash ./run.sh canonical | tee /tmp/tekton-regex-001-canonical.log\nbash ./run.sh control | tee /tmp/tekton-regex-001-control.log\ngrep -n \u0027\\\\[PROOF_MARKER\\\\]\u0027 /tmp/tekton-regex-001-canonical.log \u0026\u0026 grep -n \u0027\\\\[NC_MARKER\\\\]\u0027 /tmp/tekton-regex-001-control.log \u0026\u0026 ! grep -n \u0027\\\\[PROOF_MARKER\\\\]\u0027 /tmp/tekton-regex-001-control.log\n```\n\nsuggested patch options:\n- make matching safe-by-default by anchoring patterns before matching (or by validating and rejecting unanchored patterns).\n- document the substring semantics explicitly and update documentation examples to include anchors.\n\nworkarounds\nanchor verificationpolicy resource patterns so they must match the full source string. example:\n\n- `^https://github.com/tektoncd/catalog\\\\.git$`\n\nbest,\noleh",
  "id": "GHSA-rmx9-2pp3-xhcr",
  "modified": "2026-05-22T16:05:24Z",
  "published": "2026-04-21T16:25:19Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/tektoncd/pipeline/security/advisories/GHSA-rmx9-2pp3-xhcr"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-25542"
    },
    {
      "type": "WEB",
      "url": "https://github.com/tektoncd/pipeline/commit/2c398711e6e9e232180508f0648425a8ea34dc9e"
    },
    {
      "type": "WEB",
      "url": "https://github.com/tektoncd/pipeline/commit/b8905600322aa86327baae0a7c04d6cf1207362a"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/tektoncd/pipeline"
    },
    {
      "type": "WEB",
      "url": "https://github.com/tektoncd/pipeline/releases/tag/v1.11.0"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Tekton Pipelines has VerificationPolicy regex pattern bypass via substring matching"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…
Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.


Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…