@@ -148,10 +148,14 @@ jobs:
148148 id : pr-checkout-info
149149 if : github.event_name == 'issue_comment'
150150 timeout-minutes : 2
151+ env :
152+ ISSUE_NUMBER : ${{ github.event.issue.number }}
153+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
154+ REPO_NAME : ${{ github.repository }}
151155 run : |
152156 set -euo pipefail
153157
154- PR_NUMBER="${{ github.event.issue.number }} "
158+ PR_NUMBER="$ISSUE_NUMBER "
155159
156160 # Validate PR number
157161 if ! [[ "$PR_NUMBER" =~ ^[0-9]+$ ]]; then
@@ -164,9 +168,9 @@ jobs:
164168 # Get PR head ref with retry logic
165169 for attempt in {1..3}; do
166170 if PR_DATA=$(curl -sS --max-time 30 --retry 2 \
167- -H "Authorization: token ${{ secrets. GITHUB_TOKEN }} " \
171+ -H "Authorization: token $GITHUB_TOKEN" \
168172 -H "Accept: application/vnd.github.v3+json" \
169- "https://api.github.com/repos/${{ github.repository } }/pulls/$PR_NUMBER"); then
173+ "https://api.github.com/repos/${REPO_NAME }/pulls/$PR_NUMBER"); then
170174
171175 if echo "$PR_DATA" | jq empty 2>/dev/null; then
172176 HEAD_REF=$(echo "$PR_DATA" | jq -r '.head.ref // empty')
@@ -201,6 +205,10 @@ jobs:
201205 - name : Refresh git state
202206 id : git-refresh
203207 timeout-minutes : 3
208+ env :
209+ EVENT_NAME : ${{ github.event_name }}
210+ PR_HEAD_SHA : ${{ steps.pr-checkout-info.outputs.pr_head_sha }}
211+ PR_HEAD_REF : ${{ steps.pr-checkout-info.outputs.pr_head_ref }}
204212 run : |
205213 set -euo pipefail
206214
@@ -218,19 +226,18 @@ jobs:
218226 git fetch --all --prune
219227
220228 # For issue_comment events, ensure we're on the latest commit of the PR branch
221- if [ "${{ github.event_name }} " = "issue_comment" ]; then
222- EXPECTED_SHA="${{ steps.pr-checkout-info.outputs.pr_head_sha }} "
229+ if [ "$EVENT_NAME " = "issue_comment" ]; then
230+ EXPECTED_SHA="$PR_HEAD_SHA "
223231 echo "Expected SHA from PR: $EXPECTED_SHA"
224232
225233 # Fetch the specific PR branch to get latest changes
226- PR_HEAD_REF="${{ steps.pr-checkout-info.outputs.pr_head_ref }}"
227234 if [ -n "$PR_HEAD_REF" ]; then
228- echo "Fetching latest changes for PR branch: $PR_HEAD_REF"
229- git fetch origin "$PR_HEAD_REF:$ PR_HEAD_REF" 2>/dev/null || true
235+ echo "Fetching latest changes for PR branch: ${ PR_HEAD_REF} "
236+ git fetch origin "${ PR_HEAD_REF}:${ PR_HEAD_REF} " 2>/dev/null || true
230237
231238 # Reset to the latest commit on the PR branch
232- echo "Resetting to latest commit on $PR_HEAD_REF"
233- git reset --hard "origin/$PR_HEAD_REF"
239+ echo "Resetting to latest commit on ${ PR_HEAD_REF} "
240+ git reset --hard "origin/${ PR_HEAD_REF} "
234241
235242 NEW_SHA=$(git rev-parse HEAD)
236243 echo "Updated to SHA: $NEW_SHA"
@@ -273,6 +280,7 @@ jobs:
273280 timeout-minutes : 2
274281 env :
275282 COMMENT_BODY : ${{ github.event.comment.body }}
283+ EVENT_NAME : ${{ github.event_name }}
276284 run : |
277285 set -euo pipefail # Enhanced error handling
278286
@@ -293,7 +301,7 @@ jobs:
293301 echo "full_analysis=false" >> $GITHUB_OUTPUT
294302
295303 # Parse comment content for commands (using safe variable)
296- if [ "${{ github.event_name }} " == "issue_comment" ] || [ "${{ github.event_name }} " == "pull_request_review_comment" ]; then
304+ if [ "$EVENT_NAME " == "issue_comment" ] || [ "$EVENT_NAME " == "pull_request_review_comment" ]; then
297305 # Use grep with fixed strings where possible for security
298306 if echo "$SAFE_COMMENT" | grep -qiF "codebot hunt"; then
299307 echo "mode=hunt" >> $GITHUB_OUTPUT
@@ -349,6 +357,13 @@ jobs:
349357 - name : Get PR information
350358 id : pr-info
351359 timeout-minutes : 3
360+ env :
361+ EVENT_NAME : ${{ github.event_name }}
362+ PR_EVENT_NUMBER : ${{ github.event.pull_request.number }}
363+ PR_EVENT_BASE_REF : ${{ github.event.pull_request.base.ref }}
364+ ISSUE_EVENT_NUMBER : ${{ github.event.issue.number }}
365+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
366+ REPO_NAME : ${{ github.repository }}
352367 run : |
353368 set -euo pipefail # Enhanced error handling
354369
@@ -357,11 +372,11 @@ jobs:
357372 BASE_REF=""
358373
359374 # Handle different trigger types with validation
360- if [ "${{ github.event_name }} " = "pull_request" ]; then
361- PR_NUMBER="${{ github.event.pull_request.number }} "
362- BASE_REF="${{ github.event.pull_request.base.ref }} "
363- elif [ "${{ github.event_name }} " = "issue_comment" ]; then
364- PR_NUMBER="${{ github.event.issue.number }} "
375+ if [ "$EVENT_NAME " = "pull_request" ]; then
376+ PR_NUMBER="$PR_EVENT_NUMBER "
377+ BASE_REF="$PR_EVENT_BASE_REF "
378+ elif [ "$EVENT_NAME " = "issue_comment" ]; then
379+ PR_NUMBER="$ISSUE_EVENT_NUMBER "
365380
366381 # Validate PR number is numeric
367382 if ! [[ "$PR_NUMBER" =~ ^[0-9]+$ ]]; then
@@ -373,9 +388,9 @@ jobs:
373388 for attempt in {1..3}; do
374389 echo "Attempt $attempt: Fetching PR data for PR #$PR_NUMBER"
375390 if PR_DATA=$(curl -sS --max-time 30 --retry 2 \
376- -H "Authorization: token ${{ secrets. GITHUB_TOKEN }} " \
391+ -H "Authorization: token $GITHUB_TOKEN" \
377392 -H "Accept: application/vnd.github.v3+json" \
378- "https://api.github.com/repos/${{ github.repository } }/pulls/$PR_NUMBER"); then
393+ "https://api.github.com/repos/${REPO_NAME }/pulls/$PR_NUMBER"); then
379394
380395 # Validate JSON response
381396 if echo "$PR_DATA" | jq empty 2>/dev/null; then
@@ -396,11 +411,11 @@ jobs:
396411 sleep $((2 ** attempt))
397412 done
398413
399- elif [ "${{ github.event_name }} " = "pull_request_review_comment" ]; then
400- PR_NUMBER="${{ github.event.pull_request.number }} "
401- BASE_REF="${{ github.event.pull_request.base.ref }} "
414+ elif [ "$EVENT_NAME " = "pull_request_review_comment" ]; then
415+ PR_NUMBER="$PR_EVENT_NUMBER "
416+ BASE_REF="$PR_EVENT_BASE_REF "
402417 else
403- echo "Error: Unsupported event type: ${{ github.event_name }} "
418+ echo "Error: Unsupported event type: $EVENT_NAME "
404419 exit 1
405420 fi
406421
@@ -424,14 +439,14 @@ jobs:
424439 - name : Get changed files
425440 id : changes
426441 if : steps.parse-command.outputs.full_analysis == 'false'
442+ env :
443+ BASE_REF : ${{ steps.pr-info.outputs.base_ref }}
444+ CURRENT_SHA : ${{ steps.git-refresh.outputs.current_sha }}
445+ CURRENT_BRANCH : ${{ steps.git-refresh.outputs.current_branch }}
427446 run : |
428447
429448 set -euo pipefail
430449
431- BASE_REF="${{ steps.pr-info.outputs.base_ref }}"
432- CURRENT_SHA="${{ steps.git-refresh.outputs.current_sha }}"
433- CURRENT_BRANCH="${{ steps.git-refresh.outputs.current_branch }}"
434-
435450 echo "🔍 Detecting changed files for analysis"
436451 echo "Base branch: $BASE_REF"
437452 echo "Current SHA: $CURRENT_SHA"
@@ -533,14 +548,19 @@ jobs:
533548 - name : Verify commit SHA and git state
534549 id : verify-state
535550 timeout-minutes : 2
551+ env :
552+ REFRESHED_SHA : ${{ steps.git-refresh.outputs.current_sha }}
553+ REFRESHED_BRANCH : ${{ steps.git-refresh.outputs.current_branch }}
554+ REPO_NAME : ${{ github.repository }}
555+ EVENT_NAME : ${{ github.event_name }}
536556 run : |
537557 set -euo pipefail
538558
539559 echo "🔍 Verifying git state before analysis"
540560
541- CURRENT_SHA="${{ steps.git-refresh.outputs.current_sha }} "
561+ CURRENT_SHA="$REFRESHED_SHA "
542562 ACTUAL_SHA=$(git rev-parse HEAD)
543- CURRENT_BRANCH="${{ steps.git-refresh.outputs.current_branch }} "
563+ CURRENT_BRANCH="$REFRESHED_BRANCH "
544564
545565 # Verify SHA consistency
546566 if [ "$CURRENT_SHA" != "$ACTUAL_SHA" ]; then
@@ -561,8 +581,8 @@ jobs:
561581 echo "📊 Git state summary:"
562582 echo " Commit SHA: $CURRENT_SHA"
563583 echo " Branch: $CURRENT_BRANCH"
564- echo " Repository: ${{ github.repository }} "
565- echo " Event: ${{ github.event_name }} "
584+ echo " Repository: $REPO_NAME "
585+ echo " Event: $EVENT_NAME "
566586
567587 # Get commit info for better context
568588 COMMIT_MSG=$(git log -1 --pretty=format:"%s" 2>/dev/null || echo "Unable to get commit message")
@@ -574,7 +594,7 @@ jobs:
574594 echo " Date: $COMMIT_DATE"
575595
576596 # Create unique identifier for cache invalidation
577- REVIEW_ID="${CURRENT_SHA:0:8}-${{ github.event_name } }-$(date +%s)"
597+ REVIEW_ID="${CURRENT_SHA:0:8}-${EVENT_NAME }-$(date +%s)"
578598 echo " Review ID: $REVIEW_ID"
579599
580600 # Output additional context
@@ -669,6 +689,25 @@ jobs:
669689 - name : Workflow Summary
670690 if : always()
671691 timeout-minutes : 2
692+ env :
693+ # Pass all step outputs via env vars to prevent command injection
694+ # (attacker-controlled data like commit messages and filenames must never
695+ # be interpolated directly into shell commands via ${{ }})
696+ REVIEW_MODE : ${{ steps.parse-command.outputs.mode }}
697+ FOCUS_AREAS : ${{ steps.parse-command.outputs.focus }}
698+ VERBOSE_OUTPUT : ${{ steps.parse-command.outputs.verbose }}
699+ FULL_ANALYSIS : ${{ steps.parse-command.outputs.full_analysis || 'false' }}
700+ CHANGED_FILES : ${{ steps.changes.outputs.changed_files }}
701+ CHANGED_COUNT : ${{ steps.changes.outputs.changed_count || '0' }}
702+ DIFF_SUCCESSFUL : ${{ steps.changes.outputs.diff_successful }}
703+ PR_NUMBER : ${{ steps.pr-info.outputs.pr_number || 'N/A' }}
704+ BASE_BRANCH : ${{ steps.pr-info.outputs.base_ref || 'N/A' }}
705+ COMMIT_SHA : ${{ steps.verify-state.outputs.current_sha || steps.git-refresh.outputs.current_sha || 'Unknown' }}
706+ REVIEW_ID : ${{ steps.verify-state.outputs.review_id || 'N/A' }}
707+ CURRENT_BRANCH : ${{ steps.git-refresh.outputs.current_branch || 'Unknown' }}
708+ COMMIT_MESSAGE : ${{ steps.verify-state.outputs.commit_message || 'Unknown' }}
709+ COMMIT_AUTHOR : ${{ steps.verify-state.outputs.commit_author || 'Unknown' }}
710+ COMMIT_DATE : ${{ steps.verify-state.outputs.commit_date || 'Unknown' }}
672711 run : |
673712 set -euo pipefail # Enhanced error handling
674713
@@ -685,35 +724,40 @@ jobs:
685724
686725 # Review Configuration
687726 echo "### ⚙️ Review Configuration" >> $GITHUB_STEP_SUMMARY
688- echo "**Review Mode:** \`${{ steps.parse-command.outputs.mode }}\`" >> $GITHUB_STEP_SUMMARY
689- echo "**Focus Areas:** \`${{ steps.parse-command.outputs.focus }}\`" >> $GITHUB_STEP_SUMMARY
690- echo "**Verbose Output:** \`${{ steps.parse-command.outputs.verbose }}\`" >> $GITHUB_STEP_SUMMARY
691- echo "**Full Analysis:** \`${{ steps.parse-command.outputs.full_analysis || 'false' }}\`" >> $GITHUB_STEP_SUMMARY
692- if [ "${{ steps.parse-command.outputs.full_analysis }}" != "true" ]; then
693- echo "**Changed Files:** \`${{ steps.changes.outputs.changed_count || '0' }}\` files" >> $GITHUB_STEP_SUMMARY
694- echo "**Diff Detection:** \`${{ steps.changes.outputs.diff_successful == 'true' && 'Successful' || 'Failed' }}\`" >> $GITHUB_STEP_SUMMARY
727+ echo "**Review Mode:** \`${REVIEW_MODE}\`" >> $GITHUB_STEP_SUMMARY
728+ echo "**Focus Areas:** \`${FOCUS_AREAS}\`" >> $GITHUB_STEP_SUMMARY
729+ echo "**Verbose Output:** \`${VERBOSE_OUTPUT}\`" >> $GITHUB_STEP_SUMMARY
730+ echo "**Full Analysis:** \`${FULL_ANALYSIS}\`" >> $GITHUB_STEP_SUMMARY
731+ if [ "$FULL_ANALYSIS" != "true" ]; then
732+ DIFF_STATUS="Failed"
733+ if [ "$DIFF_SUCCESSFUL" = "true" ]; then
734+ DIFF_STATUS="Successful"
735+ fi
736+ echo "**Changed Files:** \`${CHANGED_COUNT}\` files" >> $GITHUB_STEP_SUMMARY
737+ echo "**Diff Detection:** \`${DIFF_STATUS}\`" >> $GITHUB_STEP_SUMMARY
695738 fi
696- echo "**PR Number:** \`${{ steps.pr-info.outputs.pr_number || 'N/A' } }\`" >> $GITHUB_STEP_SUMMARY
697- echo "**Base Branch:** \`${{ steps.pr-info.outputs.base_ref || 'N/A' } }\`" >> $GITHUB_STEP_SUMMARY
739+ echo "**PR Number:** \`${PR_NUMBER }\`" >> $GITHUB_STEP_SUMMARY
740+ echo "**Base Branch:** \`${BASE_BRANCH }\`" >> $GITHUB_STEP_SUMMARY
698741 echo "" >> $GITHUB_STEP_SUMMARY
699742
700743 # Git State Information
701744 echo "### 📊 Git State Analysis" >> $GITHUB_STEP_SUMMARY
702- echo "**Commit SHA:** \`${{ steps.verify-state.outputs.current_sha || steps.git-refresh.outputs.current_sha || 'Unknown' }}\`" >> $GITHUB_STEP_SUMMARY
703- echo "**Review ID:** \`${{ steps.verify-state.outputs.review_id || 'N/A' }}\`" >> $GITHUB_STEP_SUMMARY
704- echo "**Current Branch:** \`${{ steps.git-refresh.outputs.current_branch || 'Unknown' }}\`" >> $GITHUB_STEP_SUMMARY
705- echo "**Last Commit:** \"${{ steps.verify-state.outputs.commit_message || 'Unknown' }}\"" >> $GITHUB_STEP_SUMMARY
706- echo "**Author:** \`${{ steps.verify-state.outputs.commit_author || 'Unknown' }}\`" >> $GITHUB_STEP_SUMMARY
707- echo "**Date:** \`${{ steps.verify-state.outputs.commit_date || 'Unknown' }}\`" >> $GITHUB_STEP_SUMMARY
745+ echo "**Commit SHA:** \`${COMMIT_SHA}\`" >> $GITHUB_STEP_SUMMARY
746+ echo "**Review ID:** \`${REVIEW_ID}\`" >> $GITHUB_STEP_SUMMARY
747+ echo "**Current Branch:** \`${CURRENT_BRANCH}\`" >> $GITHUB_STEP_SUMMARY
748+ # Use printf to safely handle special characters in commit messages
749+ printf '**Last Commit:** "%s"\n' "$COMMIT_MESSAGE" >> $GITHUB_STEP_SUMMARY
750+ printf '**Author:** `%s`\n' "$COMMIT_AUTHOR" >> $GITHUB_STEP_SUMMARY
751+ echo "**Date:** \`${COMMIT_DATE}\`" >> $GITHUB_STEP_SUMMARY
708752 echo "" >> $GITHUB_STEP_SUMMARY
709753
710754 # Analysis Scope Details
711- if [ "${{ steps.parse-command.outputs.full_analysis }} " != "true" ] && [ "${{ steps.changes.outputs.changed_count || '0' }} " -gt "0" ]; then
755+ if [ "$FULL_ANALYSIS " != "true" ] && [ "${CHANGED_COUNT:-0} " -gt "0" ] 2>/dev/null ; then
712756 echo "### 📄 Files Being Analyzed" >> $GITHUB_STEP_SUMMARY
713757 echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
714- echo "${{ steps.changes.outputs.changed_files }} " | tr ' ' '\n' | grep -v '^$' | head -20 >> $GITHUB_STEP_SUMMARY
715- if [ "${{ steps.changes.outputs.changed_count }} " -gt "20" ]; then
716- echo "... and $((${{ steps.changes.outputs.changed_count }} - 20)) more files" >> $GITHUB_STEP_SUMMARY
758+ echo "$CHANGED_FILES " | tr ' ' '\n' | grep -v '^$' | head -20 >> $GITHUB_STEP_SUMMARY
759+ if [ "${CHANGED_COUNT:-0} " -gt "20" ] 2>/dev/null ; then
760+ echo "... and $((CHANGED_COUNT - 20)) more files" >> $GITHUB_STEP_SUMMARY
717761 fi
718762 echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
719763 echo "" >> $GITHUB_STEP_SUMMARY
0 commit comments