ci: pass untrusted workflow contexts via env to prevent shell injection (P21.1a) (#99)

This commit is contained in:
kingchenc
2026-06-01 00:32:24 +02:00
committed by GitHub
parent a046c441e5
commit debe4523d5
2 changed files with 28 additions and 7 deletions
+8 -2
View File
@@ -56,10 +56,16 @@ jobs:
- name: Run cross-library benchmark - name: Run cross-library benchmark
working-directory: bindings/python working-directory: bindings/python
# workflow_dispatch inputs are untrusted; pass them through the
# environment and quote them rather than interpolating into the shell
# command (OpenSSF Scorecard: Dangerous-Workflow).
env:
BENCH_SIZE: ${{ github.event.inputs.size || '20000' }}
BENCH_ITERATIONS: ${{ github.event.inputs.iterations || '10' }}
run: | run: |
python -m benchmarks.compare_libraries \ python -m benchmarks.compare_libraries \
--size ${{ github.event.inputs.size || '20000' }} \ --size "$BENCH_SIZE" \
--iterations ${{ github.event.inputs.iterations || '10' }} \ --iterations "$BENCH_ITERATIONS" \
--streaming-window 5000 --streaming-iterations 2 \ --streaming-window 5000 --streaming-iterations 2 \
| tee benchmark.txt | tee benchmark.txt
+20 -5
View File
@@ -74,11 +74,20 @@ jobs:
# falls back to a hard failure when push isn't possible. # falls back to a hard failure when push isn't possible.
- name: Determine if push to PR head is possible - name: Determine if push to PR head is possible
id: ctx id: ctx
# Untrusted PR contexts (head.ref / head.repo.full_name are attacker
# controlled on fork PRs) are passed through the environment, never
# interpolated straight into the shell, so a crafted branch name cannot
# inject commands (OpenSSF Scorecard: Dangerous-Workflow).
env:
EVENT_NAME: ${{ github.event_name }}
HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }}
BASE_REPO: ${{ github.repository }}
HEAD_REF: ${{ github.event.pull_request.head.ref }}
run: | run: |
if [ "${{ github.event_name }}" = "pull_request" ]; then if [ "$EVENT_NAME" = "pull_request" ]; then
if [ "${{ github.event.pull_request.head.repo.full_name }}" = "${{ github.repository }}" ]; then if [ "$HEAD_REPO" = "$BASE_REPO" ]; then
echo "can_push=true" >> "$GITHUB_OUTPUT" echo "can_push=true" >> "$GITHUB_OUTPUT"
echo "head_ref=${{ github.event.pull_request.head.ref }}" >> "$GITHUB_OUTPUT" echo "head_ref=$HEAD_REF" >> "$GITHUB_OUTPUT"
else else
echo "can_push=false" >> "$GITHUB_OUTPUT" echo "can_push=false" >> "$GITHUB_OUTPUT"
echo "head_ref=" >> "$GITHUB_OUTPUT" echo "head_ref=" >> "$GITHUB_OUTPUT"
@@ -154,12 +163,18 @@ jobs:
- name: Commit & push counter fix to PR head - name: Commit & push counter fix to PR head
if: github.event_name == 'pull_request' && steps.pr_patch.outputs.changed == 'true' if: github.event_name == 'pull_request' && steps.pr_patch.outputs.changed == 'true'
# head_ref still carries the (untrusted) PR branch name forwarded by the
# ctx step; pass it through the environment so the push refspec cannot be
# used to inject shell commands (OpenSSF Scorecard: Dangerous-Workflow).
env:
COUNT: ${{ steps.count.outputs.count }}
HEAD_REF: ${{ steps.ctx.outputs.head_ref }}
run: | run: |
git config user.name "wickra-bot" git config user.name "wickra-bot"
git config user.email "wickra-bot@users.noreply.github.com" git config user.email "wickra-bot@users.noreply.github.com"
git add README.md git add README.md
git commit -m "chore: sync indicator count to ${{ steps.count.outputs.count }}" git commit -m "chore: sync indicator count to ${COUNT}"
git push origin "HEAD:${{ steps.ctx.outputs.head_ref }}" git push origin "HEAD:${HEAD_REF}"
# ----- main / tag flow ------------------------------------------ # ----- main / tag flow ------------------------------------------
# #