From de73aa01805050225c35e35b19d7a9e804ac68d6 Mon Sep 17 00:00:00 2001 From: Alex Macdonald-Smith Date: Mon, 11 May 2026 10:46:58 -0400 Subject: [PATCH] feat(ci): least-privilege token permissions per OpenSSF Scorecard + fix semantic-pr + first-interaction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Tightens every workflow's permission scope to per-job least-privilege (top-level `contents: read`; write-scopes pushed down to the job that needs them) so OpenSSF Scorecard's `Token-Permissions` check goes from 0/10 to clean. - Fixes `semantic-pr` "Resource not accessible by integration" by adding explicit per-job `contents: read` + `pull-requests: read`. - Fixes `first-interaction` "missing issue_message input" by using the correct underscore input names (`issue_message`, `pr_message`, `repo_token`) the action actually defines — the previous dashed variants were silently dropped. --- .github/workflows/add-from-issue.yml | 8 +++++--- .github/workflows/auto-merge-dependabot.yml | 4 +++- .github/workflows/auto-merge-release-please.yml | 4 +++- .github/workflows/auto-merge.yml | 8 +++++--- .github/workflows/docs-on-release.yml | 5 ++++- .github/workflows/first-interaction.yml | 12 +++++++----- .github/workflows/labeler.yml | 4 +++- .github/workflows/lychee.yml | 4 +++- .github/workflows/outdated-watch.yml | 4 +++- .github/workflows/pages.yml | 8 ++++++-- .github/workflows/release-please.yml | 6 ++++-- .github/workflows/render.yml | 4 +++- .github/workflows/scorecard.yml | 3 ++- .github/workflows/semantic-pr.yml | 5 ++++- .github/workflows/stale.yml | 6 ++++-- .github/workflows/sync.yml | 6 ++++-- 16 files changed, 63 insertions(+), 28 deletions(-) diff --git a/.github/workflows/add-from-issue.yml b/.github/workflows/add-from-issue.yml index 84dac72..d8a128b 100644 --- a/.github/workflows/add-from-issue.yml +++ b/.github/workflows/add-from-issue.yml @@ -5,14 +5,16 @@ on: types: [opened, edited, labeled] permissions: - contents: write - issues: write - pull-requests: write + contents: read jobs: parse-and-pr: if: contains(github.event.issue.labels.*.name, 'add-repo') runs-on: ubuntu-latest + permissions: + contents: write + issues: write + pull-requests: write steps: # pin: v6.0.0 -- actions/checkout - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 diff --git a/.github/workflows/auto-merge-dependabot.yml b/.github/workflows/auto-merge-dependabot.yml index a0b3d18..d67e03c 100644 --- a/.github/workflows/auto-merge-dependabot.yml +++ b/.github/workflows/auto-merge-dependabot.yml @@ -24,7 +24,6 @@ on: permissions: contents: read - pull-requests: write concurrency: group: auto-merge-dependabot-${{ github.event.pull_request.number }} @@ -36,6 +35,9 @@ jobs: runs-on: ubuntu-latest if: github.actor == 'dependabot[bot]' timeout-minutes: 20 + permissions: + contents: read + pull-requests: write steps: - name: Fetch Dependabot metadata diff --git a/.github/workflows/auto-merge-release-please.yml b/.github/workflows/auto-merge-release-please.yml index 835f9ff..b09424f 100644 --- a/.github/workflows/auto-merge-release-please.yml +++ b/.github/workflows/auto-merge-release-please.yml @@ -30,7 +30,6 @@ on: permissions: contents: read - pull-requests: write concurrency: group: auto-merge-release-please-${{ github.event.pull_request.number }} @@ -40,6 +39,9 @@ jobs: auto-merge: name: Auto-merge release-please PR runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write # Author filter is the load-bearing safety check. release-please runs as # `release-please[bot]` on the GitHub App, or as `github-actions[bot]` # when triggered via workflow_dispatch through the action. We accept diff --git a/.github/workflows/auto-merge.yml b/.github/workflows/auto-merge.yml index 64c3e26..d17b61e 100644 --- a/.github/workflows/auto-merge.yml +++ b/.github/workflows/auto-merge.yml @@ -5,13 +5,15 @@ on: types: [opened, synchronize, reopened] permissions: - pull-requests: write - contents: write - checks: read + contents: read jobs: auto-merge: runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + checks: read steps: # pin: v6.0.0 -- actions/checkout - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 diff --git a/.github/workflows/docs-on-release.yml b/.github/workflows/docs-on-release.yml index 149233d..1a7605b 100644 --- a/.github/workflows/docs-on-release.yml +++ b/.github/workflows/docs-on-release.yml @@ -6,7 +6,7 @@ on: workflow_dispatch: permissions: - contents: write + contents: read concurrency: group: docs-on-release @@ -15,6 +15,9 @@ concurrency: jobs: update-docs: runs-on: ubuntu-latest + permissions: + contents: write + actions: write steps: # pin: v6.0.0 -- actions/checkout - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 diff --git a/.github/workflows/first-interaction.yml b/.github/workflows/first-interaction.yml index ba7f73e..27e5022 100644 --- a/.github/workflows/first-interaction.yml +++ b/.github/workflows/first-interaction.yml @@ -11,25 +11,27 @@ on: types: [opened] permissions: - issues: write - pull-requests: write + contents: read jobs: greet: runs-on: ubuntu-latest timeout-minutes: 5 + permissions: + issues: write + pull-requests: write steps: - uses: actions/first-interaction@1c4688942c71f71d4f5502a26ea67c331730fa4d # pin: v3.1.0 with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - pr-message: > + repo_token: ${{ secrets.GITHUB_TOKEN }} + pr_message: > Thanks for your first PR to understand-quickly! A maintainer will review shortly. If this adds a new entry to `registry.json`, the validate workflow will fetch your graph_url + check schema; if it adds a new graph format, `CONTRIBUTING.md` walks through the schema authoring flow. Questions: [Discussions](https://github.com/looptech-ai/understand-quickly/discussions). - issue-message: > + issue_message: > Thanks for opening your first issue! For "add my repo" requests, the [wizard](https://looptech-ai.github.io/understand-quickly/add.html) is often faster. For protocol questions, see diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 7580b6b..7982a1e 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -11,12 +11,14 @@ on: permissions: contents: read - pull-requests: write jobs: label: runs-on: ubuntu-latest timeout-minutes: 5 + permissions: + contents: read + pull-requests: write steps: - uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # pin: v5.0.0 with: diff --git a/.github/workflows/lychee.yml b/.github/workflows/lychee.yml index 4c47252..9771c0f 100644 --- a/.github/workflows/lychee.yml +++ b/.github/workflows/lychee.yml @@ -20,13 +20,15 @@ on: permissions: contents: read - issues: write jobs: link-check: name: lychee runs-on: ubuntu-latest timeout-minutes: 15 + permissions: + contents: read + issues: write steps: - name: Checkout uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # pin: v5.0.0 diff --git a/.github/workflows/outdated-watch.yml b/.github/workflows/outdated-watch.yml index 7c492c5..39c0683 100644 --- a/.github/workflows/outdated-watch.yml +++ b/.github/workflows/outdated-watch.yml @@ -16,7 +16,6 @@ on: permissions: contents: read - issues: write concurrency: group: outdated-watch @@ -27,6 +26,9 @@ jobs: name: Scan + post outdated summary runs-on: ubuntu-latest timeout-minutes: 10 + permissions: + contents: read + issues: write steps: # pin: v6.0.0 -- actions/checkout - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index b2d1dd9..419df39 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -14,8 +14,6 @@ on: permissions: contents: read - pages: write - id-token: write concurrency: group: pages @@ -24,6 +22,8 @@ concurrency: jobs: build: runs-on: ubuntu-latest + permissions: + contents: read steps: # pin: v6.0.0 -- actions/checkout - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 @@ -93,6 +93,10 @@ jobs: deploy: needs: build runs-on: ubuntu-latest + permissions: + contents: read + pages: write + id-token: write environment: name: github-pages url: ${{ steps.deploy.outputs.page_url }} diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index 7694776..1b1d4d1 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -11,12 +11,14 @@ on: workflow_dispatch: permissions: - contents: write - pull-requests: write + contents: read jobs: release: runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write steps: # pin: v4.1.5 -- googleapis/release-please-action - uses: googleapis/release-please-action@5792afc6b46e9bb55deda9eda973a18c226bc3fc diff --git a/.github/workflows/render.yml b/.github/workflows/render.yml index dd50ec2..f6f8142 100644 --- a/.github/workflows/render.yml +++ b/.github/workflows/render.yml @@ -6,12 +6,14 @@ on: paths: ['registry.json'] permissions: - contents: write + contents: read jobs: render: if: github.actor != 'github-actions[bot]' || !startsWith(github.event.head_commit.message, 'docs(readme):') runs-on: ubuntu-latest + permissions: + contents: write steps: # pin: v6.0.0 -- actions/checkout - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 0e79898..7d47fb7 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -16,7 +16,8 @@ on: branches: [main] workflow_dispatch: -permissions: read-all +permissions: + contents: read jobs: analysis: diff --git a/.github/workflows/semantic-pr.yml b/.github/workflows/semantic-pr.yml index 4082c81..34421ca 100644 --- a/.github/workflows/semantic-pr.yml +++ b/.github/workflows/semantic-pr.yml @@ -16,13 +16,16 @@ on: - synchronize permissions: - pull-requests: read + contents: read jobs: validate: name: Validate PR title runs-on: ubuntu-latest timeout-minutes: 5 + permissions: + contents: read + pull-requests: read steps: - uses: amannn/action-semantic-pull-request@e32d7e603df1aa1ba07e981f2a23455dee596825 # pin: v5.5.3 env: diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 68df936..2cb44f8 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -17,13 +17,15 @@ on: permissions: contents: read - issues: write - pull-requests: write jobs: stale: runs-on: ubuntu-latest timeout-minutes: 10 + permissions: + contents: read + issues: write + pull-requests: write steps: - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # pin: v9.1.0 with: diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml index 4f8f95d..bf1bd67 100644 --- a/.github/workflows/sync.yml +++ b/.github/workflows/sync.yml @@ -18,8 +18,7 @@ on: default: false permissions: - contents: write - actions: write + contents: read concurrency: group: sync-${{ github.event.client_payload.id || github.event.inputs.id || 'all' }} @@ -28,6 +27,9 @@ concurrency: jobs: sync: runs-on: ubuntu-latest + permissions: + contents: write + actions: write steps: # pin: v6.0.0 -- actions/checkout - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3