From 2abe11a7fe02f3ccb0df53aa89e6af1400d619e7 Mon Sep 17 00:00:00 2001 From: emozilla Date: Fri, 3 Jul 2026 12:44:30 -0400 Subject: [PATCH] security(ci): pass untrusted refs through env, not run: interpolation lint.yml inlined github.head_ref (the fork PR branch name, attacker- controlled) into the diff-summary run: block. GitHub expands ${{ }} into the script text before bash tokenizes it, so a branch like x$(id) runs on the lint runner. The pull_request trigger keeps the token read-only, but the sink still allows CI resource abuse and cache/artifact tampering, and would become RCE-with-secrets under pull_request_target. Route head_ref through an env var (env values are not subject to expression injection) and reference "$HEAD_REF". Apply the same to the two docker.yml sites that interpolate github.event.release.tag_name. Fixes GHSA-jpw6-c7jr-c56v, GHSA-2843-hjmf-7x96. Credit: @technotion, @youngstar-eth. --- .github/workflows/docker.yml | 15 ++++++++------- .github/workflows/lint.yml | 4 +++- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 8030b889e..e19894c96 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -178,6 +178,9 @@ jobs: - name: Create manifest list and push working-directory: /tmp/digests + env: + IMAGE_NAME: ${{ env.IMAGE_NAME }} + RELEASE_TAG: ${{ github.event.release.tag_name }} run: | set -euo pipefail args=() @@ -185,9 +188,8 @@ jobs: args+=("${IMAGE_NAME}@sha256:${digest_file}") done if [ "${{ github.event_name }}" = "release" ]; then - TAG="${{ github.event.release.tag_name }}" docker buildx imagetools create \ - -t "${IMAGE_NAME}:${TAG}" \ + -t "${IMAGE_NAME}:${RELEASE_TAG}" \ "${args[@]}" else docker buildx imagetools create \ @@ -195,15 +197,14 @@ jobs: -t "${IMAGE_NAME}:latest" \ "${args[@]}" fi - env: - IMAGE_NAME: ${{ env.IMAGE_NAME }} - name: Inspect image + env: + IMAGE_NAME: ${{ env.IMAGE_NAME }} + RELEASE_TAG: ${{ github.event.release.tag_name }} run: | if [ "${{ github.event_name }}" = "release" ]; then - docker buildx imagetools inspect "${IMAGE_NAME}:${{ github.event.release.tag_name }}" + docker buildx imagetools inspect "${IMAGE_NAME}:${RELEASE_TAG}" else docker buildx imagetools inspect "${IMAGE_NAME}:main" fi - env: - IMAGE_NAME: ${{ env.IMAGE_NAME }} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index fcee2c1b8..beb3a07ab 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -98,6 +98,8 @@ jobs: echo "base ty: $(wc -c < .lint-reports/base/ty.json) bytes" - name: Generate diff summary + env: + HEAD_REF: ${{ inputs.event_name == 'pull_request' && github.head_ref || github.ref_name }} run: | python scripts/lint_diff.py \ --base-ruff .lint-reports/base/ruff.json \ @@ -105,7 +107,7 @@ jobs: --base-ty .lint-reports/base/ty.json \ --head-ty .lint-reports/head/ty.json \ --base-ref "${{ steps.base.outputs.ref }}" \ - --head-ref "${{ inputs.event_name == 'pull_request' && github.head_ref || github.ref_name }}" \ + --head-ref "$HEAD_REF" \ --output .lint-reports/summary.md cat .lint-reports/summary.md >> "$GITHUB_STEP_SUMMARY"