From e83a40bf472d1b2518e0c30a389d83472221158c Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 17 Sep 2026 00:07:17 +0000 Subject: [PATCH] ci: restrict GitHub Actions cache access with cache-mode Set cache-mode to none at the workflow level and grant each job only what its setup-go and build-push-action caches need: write where a run on main saves the cache pull requests restore (ci.yml, codeql.yml, pages.yml), read where a job only restores it (the release build and the SARIF upload check). codeql.yml also gets the workflow-level permissions block the other workflows already carry, and the convention is documented next to the permissions rule. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01AKZPpJJVhgvmm2GZbX3nxV --- .github/workflows/attest-check.yml | 1 + .github/workflows/ci.yml | 7 +++++++ .github/workflows/codeql.yml | 4 ++++ .github/workflows/pages.yml | 2 ++ .github/workflows/release.yml | 2 ++ .github/workflows/sarif-upload-check.yml | 2 ++ AGENTS.md | 3 +++ 7 files changed, 21 insertions(+) diff --git a/.github/workflows/attest-check.yml b/.github/workflows/attest-check.yml index 7762262..56e346f 100644 --- a/.github/workflows/attest-check.yml +++ b/.github/workflows/attest-check.yml @@ -7,6 +7,7 @@ on: workflow_dispatch: permissions: {} +cache-mode: none env: CERT_IDENTITY_REGEXP: ^https://github\.com/bare-devcontainer/decolint/\.github/workflows/release\.yml@.*$ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 944102e..cc4e946 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,7 @@ on: pull_request: permissions: {} +cache-mode: none # The runner's default shell adds only -e, so an unset variable or a failure # mid-pipeline would otherwise pass silently. @@ -18,6 +19,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + cache-mode: write steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: @@ -32,6 +34,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + cache-mode: write steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: @@ -45,6 +48,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + cache-mode: write steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: @@ -62,6 +66,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + cache-mode: write steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: @@ -81,6 +86,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + cache-mode: write steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: @@ -95,6 +101,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + cache-mode: write steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index accdd50..3f77277 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -8,6 +8,9 @@ on: schedule: - cron: '37 18 * * 1' +permissions: {} +cache-mode: none + env: GOEXPERIMENT: "jsonv2" @@ -21,6 +24,7 @@ jobs: analyze: permissions: security-events: write + cache-mode: write name: Analyze (${{ matrix.language }}) runs-on: ubuntu-latest strategy: diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 361a540..df907c0 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -29,6 +29,7 @@ on: workflow_dispatch: permissions: {} +cache-mode: none # The runner's default shell adds only -e, so an unset variable or a failure # mid-pipeline would otherwise pass silently. @@ -41,6 +42,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + cache-mode: write steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 199bfcf..f743575 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,6 +12,7 @@ concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' }} permissions: {} +cache-mode: none env: RELEASE_REF: ${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || github.ref_name }} @@ -70,6 +71,7 @@ jobs: build: permissions: contents: read + cache-mode: read needs: prepare if: needs.prepare.outputs.skip_build != 'true' strategy: diff --git a/.github/workflows/sarif-upload-check.yml b/.github/workflows/sarif-upload-check.yml index c293beb..0d03e1a 100644 --- a/.github/workflows/sarif-upload-check.yml +++ b/.github/workflows/sarif-upload-check.yml @@ -11,6 +11,7 @@ on: - .github/workflows/sarif-upload-check.yml permissions: {} +cache-mode: none env: # A category of its own puts this check in an analysis set of its own, so it can neither replace @@ -34,6 +35,7 @@ jobs: permissions: contents: read security-events: write + cache-mode: read steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: diff --git a/AGENTS.md b/AGENTS.md index 2ea382f..5df1836 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -29,6 +29,9 @@ e.g. `uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0`. - Set workflow-level permissions to empty (`permissions: {}`) and grant the minimum required permissions per job. +- Set workflow-level cache access to none (`cache-mode: none`) and grant + the minimum required mode per job: `read` when a job only restores + caches, `write` when it also saves ones later runs restore. - Set `persist-credentials: false` on `actions/checkout`. ## Dev Container Specification