From 0a24b063870445a9298528849736e47497b456f7 Mon Sep 17 00:00:00 2001 From: Nikhil Mittal Date: Tue, 11 Aug 2026 18:55:31 +0530 Subject: [PATCH] FIX @W-19079373@ Prevent PR title injection in validate-pr workflow The validate-pr workflow interpolated the attacker-controlled github.event.pull_request.title directly into the run: shell script, allowing script injection via a crafted PR title. Pass the title (and base_ref) through environment variables (treated as data, not code) and add a least-privilege permissions block (contents: read). --- .github/workflows/validate-pr.yml | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/.github/workflows/validate-pr.yml b/.github/workflows/validate-pr.yml index 5c390ba1d..8e195dc95 100644 --- a/.github/workflows/validate-pr.yml +++ b/.github/workflows/validate-pr.yml @@ -3,6 +3,11 @@ on: pull_request: types: [edited, opened, reopened, synchronize] +# Principle of least privilege: this workflow only needs to read repository +# contents. Restricting the token limits the blast radius of any compromised step. +permissions: + contents: read + jobs: # We need to verify that the Pull Request's title matches the desired format. verify_pr_title: @@ -13,10 +18,16 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Verify PR Title + # Pass untrusted values (the PR title) via the environment rather than + # direct ${{ }} interpolation, so they are treated as data and cannot + # inject shell commands. + env: + PR_TITLE: ${{ github.event.pull_request.title }} + BASE_REF: ${{ github.base_ref }} run: | - title="${{ github.event.pull_request.title }}" + title="$PR_TITLE" title_upper=$(echo "$title" | tr '[:lower:]' '[:upper:]') - base_ref="${{ github.base_ref }}" + base_ref="$BASE_REF" # Define regex patterns for different types of PR titles MAIN2DEV_REGEX="^MAIN2DEV[[:space:]]*:?[[:space:]]*@W-[[:digit:]]{8,9}@.*MERGING.+[[:digit:]]{1,2}\.[[:digit:]]{1,2}\.[[:digit:]]{1,2}.*"