From 8863e2312d97c3bf3f6d90c9a92597deedf4e3c7 Mon Sep 17 00:00:00 2001 From: Gaurav Chaudhary Date: Fri, 2 Oct 2026 22:00:22 +0530 Subject: [PATCH] fix(ci): enforce least-privilege workflow token permissions Declare read-only defaults across GitHub Actions workflows and pass required job scopes through reusable workflow callers. Limit CodeQL, benchmark comments, release creation, and image attestation to their required permissions. Fixes #995 Signed-off-by: Gaurav Chaudhary --- .github/workflows/benchmark.yaml | 5 +++++ .github/workflows/bypass.yaml | 8 ++++++++ .github/workflows/check-ig-pin.yaml | 2 ++ .github/workflows/component-tests.yaml | 2 ++ .github/workflows/go-basic-tests.yaml | 7 +++++++ .github/workflows/incluster-comp-pr-created.yaml | 7 +++++-- .github/workflows/incluster-comp-pr-merged.yaml | 9 +++++++-- .github/workflows/pr-created.yaml | 6 ++++++ .github/workflows/pr-merged.yaml | 7 ++++--- 9 files changed, 46 insertions(+), 7 deletions(-) diff --git a/.github/workflows/benchmark.yaml b/.github/workflows/benchmark.yaml index 0c7995b784..e21a4966bc 100644 --- a/.github/workflows/benchmark.yaml +++ b/.github/workflows/benchmark.yaml @@ -28,8 +28,13 @@ concurrency: group: benchmark-${{ github.ref }} cancel-in-progress: true +permissions: read-all + jobs: benchmark: + permissions: + contents: read + pull-requests: write # Post the benchmark report on the PR. runs-on: ubuntu-large steps: - name: Checkout diff --git a/.github/workflows/bypass.yaml b/.github/workflows/bypass.yaml index a518374d5d..520190e325 100644 --- a/.github/workflows/bypass.yaml +++ b/.github/workflows/bypass.yaml @@ -2,6 +2,8 @@ name: build on: workflow_dispatch: +permissions: read-all + jobs: reset-run-number: runs-on: ubuntu-latest @@ -17,6 +19,12 @@ jobs: run-id: ${{ github.run_number }} pr-merged: + permissions: + contents: write # Create the release. + id-token: write # Sign images and attest provenance. + pull-requests: write # Required by the nested benchmark workflow. + artifact-metadata: write # Create the attested image storage record. + attestations: write needs: reset-run-number uses: ./.github/workflows/incluster-comp-pr-merged.yaml with: diff --git a/.github/workflows/check-ig-pin.yaml b/.github/workflows/check-ig-pin.yaml index 2d92e80fb6..ceeee2e66e 100644 --- a/.github/workflows/check-ig-pin.yaml +++ b/.github/workflows/check-ig-pin.yaml @@ -13,6 +13,8 @@ on: - "scripts/check-inspektor-gadget-pin.sh" - ".github/workflows/check-ig-pin.yaml" +permissions: read-all + jobs: check: name: check-ig-pin diff --git a/.github/workflows/component-tests.yaml b/.github/workflows/component-tests.yaml index 64a75c3cfd..51c1556d83 100644 --- a/.github/workflows/component-tests.yaml +++ b/.github/workflows/component-tests.yaml @@ -7,6 +7,8 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +permissions: read-all + jobs: build-and-push-image: runs-on: ubuntu-latest diff --git a/.github/workflows/go-basic-tests.yaml b/.github/workflows/go-basic-tests.yaml index 0962daa4ce..20ed2106d0 100644 --- a/.github/workflows/go-basic-tests.yaml +++ b/.github/workflows/go-basic-tests.yaml @@ -36,8 +36,11 @@ on: GITGUARDIAN_API_KEY: required: false +permissions: read-all + jobs: Check-secret: + permissions: {} name: check if secrets are set runs-on: ubuntu-latest outputs: @@ -69,6 +72,10 @@ jobs: # fi Environment-Test: + permissions: + contents: read + actions: read + security-events: write # Upload CodeQL results. name: Create cross-platform build # needs: [ Setup-Environment ] runs-on: ubuntu-latest diff --git a/.github/workflows/incluster-comp-pr-created.yaml b/.github/workflows/incluster-comp-pr-created.yaml index 53c7c4f7e4..e4633d3c7a 100644 --- a/.github/workflows/incluster-comp-pr-created.yaml +++ b/.github/workflows/incluster-comp-pr-created.yaml @@ -33,11 +33,14 @@ on: GITGUARDIAN_API_KEY: required: false +permissions: read-all + jobs: test: permissions: - pull-requests: write - security-events: write + contents: read + actions: read + security-events: write # Pass CodeQL permissions to the test workflow. uses: ./.github/workflows/go-basic-tests.yaml with: GO_VERSION: ${{ inputs.GO_VERSION }} diff --git a/.github/workflows/incluster-comp-pr-merged.yaml b/.github/workflows/incluster-comp-pr-merged.yaml index abec166606..51ec00df07 100644 --- a/.github/workflows/incluster-comp-pr-merged.yaml +++ b/.github/workflows/incluster-comp-pr-merged.yaml @@ -60,6 +60,8 @@ on: default: false type: boolean +permissions: read-all + jobs: docker-build: if: ${{ ((contains(github.event.pull_request.labels.*.name, 'release') || contains( github.event.pull_request.labels.*.name, 'trigger-integration-test')) && github.repository_owner == 'kubescape') || inputs.FORCE }} @@ -69,9 +71,8 @@ jobs: TEST_NAMES: ${{ steps.export_tests_to_env.outputs.TEST_NAMES }} permissions: id-token: write - packages: write contents: read - pull-requests: read + artifact-metadata: write # Create the attested image storage record. attestations: write # required by actions/attest-build-provenance steps: @@ -172,6 +173,7 @@ jobs: input: ${{ inputs.REQUIRED_TESTS }} run-tests: + permissions: {} # Private-repository operations use the GitHub App token. needs: docker-build if: ${{ inputs.HELM_E2E_TEST == true }} runs-on: ubuntu-latest @@ -346,6 +348,9 @@ jobs: retention-days: 7 benchmark: + permissions: + contents: read + pull-requests: write # Required by the reusable benchmark workflow. needs: docker-build if: ${{ contains(github.event.pull_request.labels.*.name, 'release') }} uses: ./.github/workflows/benchmark.yaml diff --git a/.github/workflows/pr-created.yaml b/.github/workflows/pr-created.yaml index 8f879f80a9..b3d137f218 100644 --- a/.github/workflows/pr-created.yaml +++ b/.github/workflows/pr-created.yaml @@ -11,8 +11,14 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +permissions: read-all + jobs: pr-created: + permissions: + contents: read + actions: read + security-events: write # Pass CodeQL permissions through nested workflows. uses: ./.github/workflows/incluster-comp-pr-created.yaml with: GO_VERSION: "1.27" diff --git a/.github/workflows/pr-merged.yaml b/.github/workflows/pr-merged.yaml index 66ed073d7a..bd94913b7d 100644 --- a/.github/workflows/pr-merged.yaml +++ b/.github/workflows/pr-merged.yaml @@ -10,6 +10,8 @@ on: workflow_dispatch: +permissions: read-all + jobs: reset-run-number: runs-on: ubuntu-latest @@ -28,11 +30,10 @@ jobs: if: ${{ github.event.pull_request.merged == true }} ## Skip if not merged needs: reset-run-number permissions: - actions: read id-token: write - packages: write contents: write - pull-requests: read + pull-requests: write # Required by the nested benchmark workflow. + artifact-metadata: write # Create the attested image storage record. attestations: write # required by actions/attest-build-provenance in the shared workflow uses: ./.github/workflows/incluster-comp-pr-merged.yaml with: