-
Notifications
You must be signed in to change notification settings - Fork 31
fix: add missing Checkout-GhAwPr.ps1 script #788
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| #!/usr/bin/env pwsh | ||
| # Checkout-GhAwPr.ps1 — Security-checked PR checkout for gh-aw workflow_dispatch. | ||
| # | ||
| # Verifies the PR author has write access to the repo, checks out the PR branch, | ||
| # then restores .github/ from the base branch (main) to prevent prompt injection | ||
| # via modified workflow files in the PR. | ||
|
|
||
| $ErrorActionPreference = 'Stop' | ||
|
|
||
| $prNumber = $env:PR_NUMBER | ||
| if (-not $prNumber) { | ||
| Write-Error "PR_NUMBER environment variable is required" | ||
| exit 1 | ||
| } | ||
|
|
||
| Write-Host "Checking out PR #$prNumber..." | ||
|
|
||
| # Get PR info | ||
| $prJson = gh pr view $prNumber --json headRefName,headRepository,headRepositoryOwner,author,baseRefName --repo $env:GITHUB_REPOSITORY 2>&1 | ||
| if ($LASTEXITCODE -ne 0) { | ||
| Write-Error "Failed to get PR #$prNumber info: $prJson" | ||
| exit 1 | ||
| } | ||
| $pr = $prJson | ConvertFrom-Json | ||
|
|
||
| $branch = $pr.headRefName | ||
| $baseBranch = $pr.baseRefName | ||
| $author = $pr.author.login | ||
|
|
||
| Write-Host "PR #$prNumber by $author, branch: $branch, base: $baseBranch" | ||
|
|
||
| # Check author has write access (skip for bots) | ||
| if ($author -notmatch '\[bot\]$') { | ||
| $permJson = gh api "repos/$($env:GITHUB_REPOSITORY)/collaborators/$author/permission" --jq '.permission' 2>&1 | ||
| if ($LASTEXITCODE -ne 0) { | ||
| Write-Warning "Could not verify author permissions: $permJson" | ||
| } else { | ||
| $perm = $permJson.Trim() | ||
| if ($perm -notin @('admin', 'maintain', 'write')) { | ||
| Write-Error "Author '$author' has '$perm' permission — write access required for workflow_dispatch review" | ||
| exit 1 | ||
| } | ||
| Write-Host "Author '$author' has '$perm' access — OK" | ||
| } | ||
| } | ||
|
|
||
| # Fetch and checkout the PR branch | ||
| git fetch origin "pull/$prNumber/head:pr-$prNumber" 2>&1 | Write-Host | ||
| git checkout "pr-$prNumber" 2>&1 | Write-Host | ||
|
|
||
| # Save the PR HEAD SHA | ||
| $prSha = git rev-parse HEAD | ||
| Write-Host "PR HEAD: $prSha" | ||
|
|
||
| # Restore .github/ from the base branch to prevent workflow tampering | ||
| Write-Host "Restoring .github/ from $baseBranch..." | ||
| git checkout "origin/$baseBranch" -- .github/ 2>&1 | Write-Host | ||
|
Comment on lines
+48
to
+57
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 CRITICAL · 3/3 reviewers ·
Fix: Check git fetch origin "pull/$prNumber/head:pr-$prNumber" 2>&1 | Write-Host
if ($LASTEXITCODE -ne 0) { Write-Error "git fetch failed"; exit 1 }
git checkout "pr-$prNumber" 2>&1 | Write-Host
if ($LASTEXITCODE -ne 0) { Write-Error "git checkout failed"; exit 1 }
# ... same for line 57's .github/ restore
git checkout "origin/$baseBranch" -- .github/ 2>&1 | Write-Host
if ($LASTEXITCODE -ne 0) { Write-Error ".github/ restore failed"; exit 1 }Alternatively, use
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 MODERATE · 3/3 reviewers · The script only fetches Fix: Fetch the base ref before restoring (prefer immutable SHA via # Add baseRefOid to the gh pr view --json fields
$baseSha = $pr.baseRefOid
git fetch origin $baseSha 2>&1 | Write-Host
if ($LASTEXITCODE -ne 0) { Write-Error "Failed to fetch base ref"; exit 1 }
git checkout $baseSha -- .github/ 2>&1 | Write-Host
if ($LASTEXITCODE -ne 0) { Write-Error "Failed to restore .github/"; exit 1 } |
||
|
|
||
| Write-Host "Checkout complete — PR #$prNumber on branch $branch, .github/ from $baseBranch" | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔴 CRITICAL · 3/3 reviewers · Permission check fail-open — API failure silently bypasses access gate
The collaborators API returns HTTP 404 for non-collaborators (the exact users this gate should block). When
$LASTEXITCODE -ne 0, the script logs aWrite-Warningand continues — the checkout proceeds without any authorization check. This also triggers on rate limits, insufficient token scope, or network errors.Scenario: A fork PR author with read-only access triggers
workflow_dispatch. The API returns 404, the warning is logged and ignored, and the untrusted PR is checked out and reviewed.Fix: Fail closed — treat API failure as denied: