From bff4ef31245cabeaa046fb862cb15cabe71d7c26 Mon Sep 17 00:00:00 2001 From: amagan Date: Fri, 14 Aug 2026 13:45:42 +0200 Subject: [PATCH] fix(ci): harden workflows (least-privilege permissions, action pinning, open PR checks) F-CI-001: remove the repo-admin gate from code-npm_node-PR_verify.yml so external contributors' fork PRs can run read-only lint/test/build. The job runs on pull_request (no secret exposure) with permissions: contents: read. F-SEC-003: add least-privilege permissions to PR_verify, PR_verify-fallback and the four release_preview jobs (clears the missing-workflow-permissions alerts); SHA-pin actions/create-github-app-token@v3 and actions/setup-java@v5. Note: the issue_comment '/publish-snapshot' publisher (F-SEC-001) is intentionally left untouched here; it will be redesigned separately (untrusted build vs trusted publish, immutable artifact hand-off, environment with required reviewers). --- .github/workflows/code-PR_verify-fallback.yml | 1 + .github/workflows/code-npm_node-PR_verify.yml | 20 ++----------------- ...-npm_node-publish-release-and-snapshot.yml | 2 +- .../code-npm_node-sonarcloud-analysis.yml | 2 +- .github/workflows/code-release_preview.yml | 10 ++++++++++ 5 files changed, 15 insertions(+), 20 deletions(-) diff --git a/.github/workflows/code-PR_verify-fallback.yml b/.github/workflows/code-PR_verify-fallback.yml index c2bec02..8da3e7a 100644 --- a/.github/workflows/code-PR_verify-fallback.yml +++ b/.github/workflows/code-PR_verify-fallback.yml @@ -11,5 +11,6 @@ jobs: if: "false" name: Code / Verify runs-on: ubuntu-24.04 + permissions: {} steps: - run: echo "No Code / Verify required" diff --git a/.github/workflows/code-npm_node-PR_verify.yml b/.github/workflows/code-npm_node-PR_verify.yml index c05eeb8..1d3acea 100644 --- a/.github/workflows/code-npm_node-PR_verify.yml +++ b/.github/workflows/code-npm_node-PR_verify.yml @@ -28,27 +28,11 @@ jobs: name: Code / Verify timeout-minutes: 60 runs-on: ubuntu-24.04 + permissions: + contents: read env: ASDF_BRANCH_VERSION: 0.18.0 steps: - - name: Validate admin permissions - id: permission-check - uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7 - with: - script: | - const { data } = await github.rest.repos.getCollaboratorPermissionLevel({ - owner: context.repo.owner, - repo: context.repo.repo, - username: context.actor - }); - - const permission = data.permission; - core.info(`User permission level: ${permission}`); - - if (permission !== "admin") { - core.setFailed(`User @${context.actor} is not a repository admin.`); - } - - name: Checkout / Branch Head uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: diff --git a/.github/workflows/code-npm_node-publish-release-and-snapshot.yml b/.github/workflows/code-npm_node-publish-release-and-snapshot.yml index 8a9d65f..b8016ca 100644 --- a/.github/workflows/code-npm_node-publish-release-and-snapshot.yml +++ b/.github/workflows/code-npm_node-publish-release-and-snapshot.yml @@ -332,7 +332,7 @@ jobs: BASELINE_BRANCH=${{ github.event.inputs.BASELINE || github.ref }} echo "BASELINE_BRANCH=${BASELINE_BRANCH#refs/heads/}" >> "$GITHUB_ENV" - - uses: actions/create-github-app-token@v3 + - uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3 id: app-token with: client-id: ${{ vars.APP_CLIENT_ID }} diff --git a/.github/workflows/code-npm_node-sonarcloud-analysis.yml b/.github/workflows/code-npm_node-sonarcloud-analysis.yml index af741c2..793915c 100644 --- a/.github/workflows/code-npm_node-sonarcloud-analysis.yml +++ b/.github/workflows/code-npm_node-sonarcloud-analysis.yml @@ -120,7 +120,7 @@ jobs: - name: Set up JDK 21 for SonarScanner if: steps.project.outputs.has-package == 'true' - uses: actions/setup-java@v5 + uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5 with: distribution: temurin java-version: "21" diff --git a/.github/workflows/code-release_preview.yml b/.github/workflows/code-release_preview.yml index f96c8f7..f96e67f 100644 --- a/.github/workflows/code-release_preview.yml +++ b/.github/workflows/code-release_preview.yml @@ -19,6 +19,9 @@ jobs: check-changes-in-paths: name: Check for changes in corresponding paths runs-on: ubuntu-24.04 + permissions: + contents: read + pull-requests: read if: ${{ github.event.pull_request.draft == false || contains(join(github.event.pull_request.labels.*.name, ', '), 'release-type') || contains(join(github.event.pull_request.labels.*.name, ', '), 'release-preview') }} outputs: detected: ${{ steps.changes.outputs.paths }} @@ -42,6 +45,9 @@ jobs: needs: check-changes-in-paths if: ${{ (contains(join(github.event.pull_request.labels.*.name, ', '), 'release-type') || contains(join(github.event.pull_request.labels.*.name, ', '), 'release-preview')) && needs.check-changes-in-paths.outputs.detected == 'true' }} runs-on: ubuntu-24.04 + permissions: + contents: read + pull-requests: write steps: - name: Checkout merge commit uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 @@ -130,6 +136,8 @@ jobs: needs: check-changes-in-paths if: ${{ (contains(join(github.event.pull_request.labels.*.name, ', '), 'release-type') || contains(join(github.event.pull_request.labels.*.name, ', '), 'release-preview')) && needs.check-changes-in-paths.outputs.detected == 'false' }} runs-on: ubuntu-24.04 + permissions: + pull-requests: write env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: @@ -144,6 +152,8 @@ jobs: needs: check-changes-in-paths if: ${{ !contains(join(github.event.pull_request.labels.*.name, ', '), 'release-type') && needs.check-changes-in-paths.outputs.detected == 'true' && github.event.pull_request.draft == false && vars.DEVELOPMENT_FLOW != 'trunk-based-development' }} runs-on: ubuntu-24.04 + permissions: + pull-requests: write env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: