From d15d7d0962f3a1574483d155b611ce03dd06eae6 Mon Sep 17 00:00:00 2001 From: zsxsoft Date: Tue, 31 Mar 2026 03:04:24 +0000 Subject: [PATCH] fix(scripts/pr): shell-escape env file values to prevent command injection via branch names --- scripts/pr-lib/gates.sh | 19 ++++++------- scripts/pr-lib/prepare-core.sh | 49 ++++++++++++++++++---------------- scripts/pr-lib/push.sh | 11 ++++---- scripts/pr-lib/review.sh | 29 +++++++++++--------- scripts/pr-lib/worktree.sh | 39 ++++++++++++++++++--------- 5 files changed, 85 insertions(+), 62 deletions(-) diff --git a/scripts/pr-lib/gates.sh b/scripts/pr-lib/gates.sh index 679269fd3b1..bd9cc818040 100644 --- a/scripts/pr-lib/gates.sh +++ b/scripts/pr-lib/gates.sh @@ -114,15 +114,16 @@ prepare_gates() { fi fi - cat > .local/gates.env < .local/gates.env echo "docs_only=$docs_only" echo "changelog_required=$changelog_required" diff --git a/scripts/pr-lib/prepare-core.sh b/scripts/pr-lib/prepare-core.sh index b6874aaafe9..f4347ed4109 100644 --- a/scripts/pr-lib/prepare-core.sh +++ b/scripts/pr-lib/prepare-core.sh @@ -78,13 +78,14 @@ prepare_init() { git checkout -B "pr-$pr-prep" "pr-$pr" git fetch origin main - cat > .local/prep-context.env < .local/prep-context.env if [ ! -f .local/prep.md ]; then cat > .local/prep.md < .local/prep.env < .local/prep.env ls -la .local/prep.md .local/prep.env >/dev/null @@ -245,14 +247,15 @@ prepare_sync_head() { - Prepare gates reran automatically when the sync rebase changed the prep head. EOF_PREP - cat > .local/prep.env < .local/prep.env ls -la .local/prep.md .local/prep.env >/dev/null diff --git a/scripts/pr-lib/push.sh b/scripts/pr-lib/push.sh index 99d96589910..ca5bae22ed0 100644 --- a/scripts/pr-lib/push.sh +++ b/scripts/pr-lib/push.sh @@ -288,9 +288,10 @@ push_prep_head_to_pr_branch() { exit 1 } git branch -D "pr-$pr-verify" 2>/dev/null || true - cat > "$result_env_path" < "$result_env_path" } diff --git a/scripts/pr-lib/review.sh b/scripts/pr-lib/review.sh index 4c36977a937..1e26f5f761d 100644 --- a/scripts/pr-lib/review.sh +++ b/scripts/pr-lib/review.sh @@ -1,9 +1,10 @@ set_review_mode() { local mode="$1" - cat > .local/review-mode.env < .local/review-mode.env } review_claim() { @@ -482,10 +483,11 @@ review_tests() { exit 1 fi - { - echo "REVIEW_TESTS_AT=$(date -u +%Y-%m-%dT%H:%M:%SZ)" - echo "REVIEW_TEST_TARGET_COUNT=$#" - } > .local/review-tests.env + # Security: shell-escape values to prevent command injection when sourced. + printf '%s=%q\n' \ + REVIEW_TESTS_AT "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ + REVIEW_TEST_TARGET_COUNT "$#" \ + > .local/review-tests.env echo "review tests passed and were observed in output" } @@ -502,11 +504,12 @@ review_init() { local mb mb=$(git merge-base origin/main "pr-$pr") - cat > .local/review-context.env < .local/review-context.env set_review_mode main printf '%s\n' "$json" | jq '{number,title,url,state,isDraft,author:.author.login,base:.baseRefName,head:.headRefName,headSha:.headRefOid,headRepo:.headRepository.nameWithOwner,additions,deletions,files:(.files|length)}' diff --git a/scripts/pr-lib/worktree.sh b/scripts/pr-lib/worktree.sh index 1dfc7499d73..a5f42d208da 100644 --- a/scripts/pr-lib/worktree.sh +++ b/scripts/pr-lib/worktree.sh @@ -55,18 +55,33 @@ write_pr_meta_files() { printf '%s\n' "$json" > .local/pr-meta.json - cat > .local/pr-meta.env < .local/pr-meta.env } list_pr_worktrees() {