From f10d94e268e0133574e5e0a4a0de68fac21455f7 Mon Sep 17 00:00:00 2001 From: rtibblesbot Date: Sat, 16 May 2026 10:55:39 -0700 Subject: [PATCH 1/4] security(workflows): restrict GITHUB_TOKEN to contents:read on call-* shims All write operations in these workflows are performed by the LE bot app token (LE_BOT_APP_ID / LE_BOT_PRIVATE_KEY). The GITHUB_TOKEN itself requires only contents:read for the reusable-workflow call to be bounded. Addresses CodeQL actions/missing-workflow-permissions alerts. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/call-contributor-issue-comment.yml | 3 +++ .github/workflows/call-contributor-pr-reply.yml | 4 ++++ .github/workflows/call-manage-issue-header.yml | 3 +++ .github/workflows/call-pull-request-target.yml | 4 ++++ .github/workflows/call-update-pr-spreadsheet.yml | 3 +++ .github/workflows/community-contribution-labeling.yml | 3 +++ .github/workflows/unassign-inactive.yaml | 3 +++ 7 files changed, 23 insertions(+) diff --git a/.github/workflows/call-contributor-issue-comment.yml b/.github/workflows/call-contributor-issue-comment.yml index 4e8b7db1c3..a47ee7b28d 100644 --- a/.github/workflows/call-contributor-issue-comment.yml +++ b/.github/workflows/call-contributor-issue-comment.yml @@ -4,6 +4,9 @@ on: issue_comment: types: [created] +permissions: + contents: read + jobs: call-workflow: uses: learningequality/.github/.github/workflows/contributor-issue-comment.yml@main diff --git a/.github/workflows/call-contributor-pr-reply.yml b/.github/workflows/call-contributor-pr-reply.yml index e8316e041b..ac84d3db82 100644 --- a/.github/workflows/call-contributor-pr-reply.yml +++ b/.github/workflows/call-contributor-pr-reply.yml @@ -2,6 +2,10 @@ name: Send reply on a new contributor pull request on: pull_request_target: types: [opened] + +permissions: + contents: read + jobs: call-workflow: name: Call shared workflow diff --git a/.github/workflows/call-manage-issue-header.yml b/.github/workflows/call-manage-issue-header.yml index 4af6730ac2..c511eef0b2 100644 --- a/.github/workflows/call-manage-issue-header.yml +++ b/.github/workflows/call-manage-issue-header.yml @@ -4,6 +4,9 @@ on: issues: types: [opened, reopened, labeled, unlabeled] +permissions: + contents: read + jobs: call-workflow: name: Call shared workflow diff --git a/.github/workflows/call-pull-request-target.yml b/.github/workflows/call-pull-request-target.yml index e499bcddf8..d3cc282b91 100644 --- a/.github/workflows/call-pull-request-target.yml +++ b/.github/workflows/call-pull-request-target.yml @@ -2,6 +2,10 @@ name: Handle pull request events on: pull_request_target: types: [opened, review_requested, labeled] + +permissions: + contents: read + jobs: call-workflow: name: Call shared workflow diff --git a/.github/workflows/call-update-pr-spreadsheet.yml b/.github/workflows/call-update-pr-spreadsheet.yml index 35464d6b02..5972bbc785 100644 --- a/.github/workflows/call-update-pr-spreadsheet.yml +++ b/.github/workflows/call-update-pr-spreadsheet.yml @@ -3,6 +3,9 @@ on: pull_request_target: types: [assigned, unassigned, opened, closed, reopened, edited, review_requested, review_request_removed] +permissions: + contents: read + jobs: call-workflow: name: Call shared workflow diff --git a/.github/workflows/community-contribution-labeling.yml b/.github/workflows/community-contribution-labeling.yml index 701465ba1c..57953db099 100644 --- a/.github/workflows/community-contribution-labeling.yml +++ b/.github/workflows/community-contribution-labeling.yml @@ -4,6 +4,9 @@ on: issues: types: [assigned, unassigned] +permissions: + contents: read + jobs: call-label-action: uses: learningequality/.github/.github/workflows/community-contribution-label.yml@main diff --git a/.github/workflows/unassign-inactive.yaml b/.github/workflows/unassign-inactive.yaml index 4151166a6d..78f2e110b4 100644 --- a/.github/workflows/unassign-inactive.yaml +++ b/.github/workflows/unassign-inactive.yaml @@ -6,6 +6,9 @@ on: - cron: "1 0 * * 1" # Every Monday at 00:01 UTC workflow_dispatch: +permissions: + contents: read + jobs: unassign-inactive: uses: learningequality/.github/.github/workflows/unassign-inactive-issues.yaml@main From 18fc023cc56aaffc59174641e23f371bf53739a9 Mon Sep 17 00:00:00 2001 From: rtibblesbot Date: Sat, 16 May 2026 10:56:06 -0700 Subject: [PATCH 2/4] security(workflows): restrict GITHUB_TOKEN to contents:read on lint and i18n workflows pre-commit.yml: fkirc/skip-duplicate-actions degrades gracefully to always-run when it cannot read workflow runs; the tighter scope is preferred per the audit. i18n-download.yml: PR creation uses the LE bot app token, not GITHUB_TOKEN, so no write scope is needed. Addresses CodeQL actions/missing-workflow-permissions alerts. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/i18n-download.yml | 3 +++ .github/workflows/i18n-upload.yml | 3 +++ .github/workflows/pre-commit.yml | 3 +++ 3 files changed, 9 insertions(+) diff --git a/.github/workflows/i18n-download.yml b/.github/workflows/i18n-download.yml index b4810d331d..cdaa38687a 100644 --- a/.github/workflows/i18n-download.yml +++ b/.github/workflows/i18n-download.yml @@ -3,6 +3,9 @@ name: Download translations from Crowdin on: workflow_dispatch: +permissions: + contents: read + jobs: download: name: Download translations and update files diff --git a/.github/workflows/i18n-upload.yml b/.github/workflows/i18n-upload.yml index 38816e944d..8235a53de9 100644 --- a/.github/workflows/i18n-upload.yml +++ b/.github/workflows/i18n-upload.yml @@ -3,6 +3,9 @@ name: Upload translations to Crowdin on: workflow_dispatch: +permissions: + contents: read + jobs: upload: name: Extract and upload strings to Crowdin diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 14ff4ac2fd..6efea7fad5 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -12,6 +12,9 @@ on: - hotfixes - master +permissions: + contents: read + jobs: pre_job: name: Path match check From f2dfe927ab5c58cbb6895524acdf251c98b82ca4 Mon Sep 17 00:00:00 2001 From: rtibblesbot Date: Sat, 16 May 2026 10:56:32 -0700 Subject: [PATCH 3/4] security(workflows): restrict CI workflows to contents:read + actions:read fkirc/skip-duplicate-actions requires actions:read to query prior workflow runs. contents:read is required for actions/checkout. No write operations are performed by GITHUB_TOKEN in these workflows. Addresses CodeQL actions/missing-workflow-permissions alerts. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/deploytest.yml | 4 ++++ .github/workflows/frontendtest.yml | 4 ++++ .github/workflows/pythontest.yml | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/.github/workflows/deploytest.yml b/.github/workflows/deploytest.yml index 03f71f6ce7..8d29504876 100644 --- a/.github/workflows/deploytest.yml +++ b/.github/workflows/deploytest.yml @@ -8,6 +8,10 @@ on: - master pull_request: +permissions: + contents: read + actions: read + jobs: pre_job: name: Path match check diff --git a/.github/workflows/frontendtest.yml b/.github/workflows/frontendtest.yml index 76de0dad94..e995328d09 100644 --- a/.github/workflows/frontendtest.yml +++ b/.github/workflows/frontendtest.yml @@ -8,6 +8,10 @@ on: - master pull_request: +permissions: + contents: read + actions: read + jobs: pre_job: name: Path match check diff --git a/.github/workflows/pythontest.yml b/.github/workflows/pythontest.yml index e77c613e69..0c4a0545ca 100644 --- a/.github/workflows/pythontest.yml +++ b/.github/workflows/pythontest.yml @@ -8,6 +8,10 @@ on: - master pull_request: +permissions: + contents: read + actions: read + jobs: pre_job: name: Path match check From 1f37621127d4b91ed8889cdeaec883b1ed19924e Mon Sep 17 00:00:00 2001 From: rtibblesbot Date: Sat, 16 May 2026 10:56:48 -0700 Subject: [PATCH 4/4] security(workflows): restrict containerbuild to contents:read + packages:write The postgres job logs in to ghcr.io with GITHUB_TOKEN and pushes the image on non-PR runs, requiring packages:write. The nginx job only test-builds and never pushes, but the scope is declared at workflow level. contents:read covers actions/checkout. Addresses CodeQL actions/missing-workflow-permissions alerts. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/containerbuild.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/containerbuild.yml b/.github/workflows/containerbuild.yml index 0dc9af1f07..f46f47d079 100644 --- a/.github/workflows/containerbuild.yml +++ b/.github/workflows/containerbuild.yml @@ -10,6 +10,10 @@ on: - 'v*' pull_request: +permissions: + contents: read + packages: write + jobs: pre_postgres: name: Path match check - postgres