mirror of
https://github.com/avelino/awesome-go.git
synced 2026-04-11 02:11:43 +08:00
The pull_request_target workflow checked out and executed Go scripts from the PR head, allowing attackers to inject arbitrary code via init() functions with access to a write-scoped GITHUB_TOKEN. This was confirmed exploited in the wild (ref: StepSecurity blog). Checkout now targets the base branch so only trusted scripts execute. PR head SHA is fetched as data-only for diffing via a new PR_HEAD_SHA env var. Write operations (comments, labels) are isolated in a separate report job that never checks out code. All job permissions follow least privilege — quality runs read-only, report holds the write token. fixed: #6083 Signed-off-by: Avelino <31996+avelino@users.noreply.github.com> Co-Authored-By: Thierry Abalea <thierry.abalea@shipfox.io>
148 lines
4.8 KiB
YAML
148 lines
4.8 KiB
YAML
name: PR Quality Checks
|
|
|
|
on:
|
|
pull_request_target:
|
|
types: [opened, edited, synchronize, reopened]
|
|
|
|
permissions:
|
|
contents: read
|
|
pull-requests: read
|
|
|
|
jobs:
|
|
detect:
|
|
name: Detect PR type
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
is_package_pr: ${{ steps.check.outputs.is_package_pr }}
|
|
steps:
|
|
- name: Check if README.md is modified
|
|
id: check
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
files=$(gh api repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/files --jq '.[].filename' 2>/dev/null || echo "")
|
|
if echo "$files" | grep -q '^README.md$'; then
|
|
echo "is_package_pr=true" >> "$GITHUB_OUTPUT"
|
|
echo "README.md is modified — this is a package PR"
|
|
else
|
|
echo "is_package_pr=false" >> "$GITHUB_OUTPUT"
|
|
echo "README.md not modified — skipping quality checks"
|
|
fi
|
|
|
|
quality:
|
|
name: Repository quality checks
|
|
needs: detect
|
|
if: needs.detect.outputs.is_package_pr == 'true'
|
|
runs-on: ubuntu-latest
|
|
environment: action
|
|
container: golang:latest
|
|
permissions:
|
|
contents: read
|
|
pull-requests: read
|
|
outputs:
|
|
comment: ${{ steps.quality.outputs.comment }}
|
|
labels: ${{ steps.quality.outputs.labels }}
|
|
fail: ${{ steps.quality.outputs.fail }}
|
|
diff_comment: ${{ steps.diff.outputs.diff_comment }}
|
|
diff_fail: ${{ steps.diff.outputs.diff_fail }}
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
with:
|
|
ref: ${{ github.event.pull_request.base.sha }}
|
|
persist-credentials: false
|
|
fetch-depth: 0
|
|
|
|
- name: Fetch base branch and PR head
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
|
AUTH="$(printf '%s' "x-access-token:${GITHUB_TOKEN}" | base64 -w0)"
|
|
git -c "http.https://github.com/.extraheader=AUTHORIZATION: basic ${AUTH}" fetch origin "${{ github.base_ref }}"
|
|
git -c "http.https://github.com/.extraheader=AUTHORIZATION: basic ${AUTH}" fetch origin "+refs/pull/${{ github.event.pull_request.number }}/head"
|
|
|
|
- name: Run quality checks
|
|
id: quality
|
|
continue-on-error: true
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: go run ./.github/scripts/check-quality/
|
|
|
|
- name: Run diff checks
|
|
id: diff
|
|
continue-on-error: true
|
|
env:
|
|
GITHUB_BASE_REF: ${{ github.base_ref }}
|
|
PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
|
run: go run ./.github/scripts/check-pr-diff/
|
|
|
|
report:
|
|
name: Post quality report
|
|
needs: [detect, quality]
|
|
if: always() && needs.detect.outputs.is_package_pr == 'true' && needs.quality.result != 'cancelled'
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
pull-requests: write
|
|
contents: write
|
|
steps:
|
|
- name: Post quality report comment
|
|
uses: marocchino/sticky-pull-request-comment@v2
|
|
with:
|
|
header: pr-quality-check
|
|
message: |
|
|
${{ needs.quality.outputs.comment }}
|
|
|
|
---
|
|
|
|
${{ needs.quality.outputs.diff_comment }}
|
|
|
|
- name: Sync labels
|
|
if: needs.quality.outputs.labels != ''
|
|
uses: actions-ecosystem/action-add-labels@v1
|
|
with:
|
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
labels: ${{ join(fromJson(needs.quality.outputs.labels), '\n') }}
|
|
|
|
- name: Fail if critical checks failed
|
|
if: needs.quality.outputs.fail == 'true' || needs.quality.outputs.diff_fail == 'true'
|
|
run: |
|
|
echo "Quality or diff checks failed."
|
|
exit 1
|
|
|
|
skip-notice:
|
|
name: Skip quality checks (non-package PR)
|
|
needs: detect
|
|
if: needs.detect.outputs.is_package_pr == 'false'
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
pull-requests: write
|
|
steps:
|
|
- name: Post skip notice
|
|
uses: marocchino/sticky-pull-request-comment@v2
|
|
with:
|
|
header: pr-quality-check
|
|
message: |
|
|
## Automated Quality Checks
|
|
|
|
**Skipped** — this PR does not modify `README.md`, so package quality checks do not apply.
|
|
|
|
_This is expected for maintenance, documentation, or workflow PRs._
|
|
|
|
auto-merge:
|
|
name: Enable auto-merge
|
|
needs: [quality, report]
|
|
if: always() && needs.quality.result == 'success' && needs.report.result == 'success'
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: write
|
|
pull-requests: write
|
|
steps:
|
|
- name: Enable auto-merge via squash
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
gh pr merge ${{ github.event.pull_request.number }} \
|
|
--repo ${{ github.repository }} \
|
|
--auto \
|
|
--squash
|