Skip to content

chore(ci): limit GITHUB_TOKEN to read-only in ten workflows - #8054

Open
yhabib wants to merge 1 commit into
mainfrom
chore/add-deploy-docker-reproducible-permissions
Open

chore(ci): limit GITHUB_TOKEN to read-only in ten workflows#8054
yhabib wants to merge 1 commit into
mainfrom
chore/add-deploy-docker-reproducible-permissions

Conversation

@yhabib

@yhabib yhabib commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Motivation

Ten workflows have no permissions: key, so their jobs hold the repository default GITHUB_TOKEN, which is read and write. None of them writes to the repository with that token.

Changes

  • Added a workflow-level permissions: contents: read block to the ten workflows with no permissions key: deploy-to-app.yaml, docker-main.yaml, reproducible.yaml, and the seven update-* bot workflows.
  • Left every job without its own permissions block, so the workflow-level block applies to all twelve jobs.

Tests

  • Confirmed with yq that all ten files declare contents: read and no job carries its own block.
  • Dispatched three workflows from the branch and confirmed each ran green with the token scoped to Contents: read and Metadata: read: run 33928930943 (docker-main.yaml), run 33928933301 (update-snsdemo.yml), run 33928935284 (reproducible.yaml).
  • Ran actionlint 1.7.7 against the ten files on main and on the branch. The finding sets match exactly, 8 pre-existing findings on each side, so the new blocks add no schema error.
  • Did not dispatch deploy-to-app.yaml: it installs canisters on mainnet with real funds. Its only GITHUB_TOKEN use is the checkout inside checkout_snsdemo and build_nns_dapp, which a sibling PR (chore(ci): add least-privilege permissions to build.yml and checks.yml #8053) already runs green under contents: read.
  • Ran ./scripts/fmt-yaml --check: exit 0.

Todos

  • Accessibility (a11y) – no impact, this only changes CI workflow files.
  • Changelog – not needed, a workflow permissions change is not user facing.
  • This is part 3 of 4 split out of item 1788181556. The sibling parts are 1788562415 (PR chore(ci): add least-privilege permissions to build.yml and checks.yml #8053), 1788562416, and 1788562418. Each lands its own pull request.
  • Follow-up not made here: deploy-to-app.yaml lines 60 and 89 pass token: ${{ secrets.GITHUB_TOKEN }} to two composite actions that never read it. Removing it also touches build.yml and nightly.yaml, so it needs its own item.

Ten workflows declare no permissions key. Their jobs hold the repository
default GITHUB_TOKEN, which is read and write. None of them writes with
that token.

Add a workflow-level block with contents: read to each file.

- The seven update-* workflows push and open pull requests with a GitHub
  App token from actions/create-github-app-token, not with GITHUB_TOKEN.
- deploy-to-app.yaml deploys with the DFX_IDENTITY_PEM identity. It passes
  secrets.GITHUB_TOKEN to checkout_snsdemo and build_nns_dapp, and neither
  composite action uses the input.
- docker-main.yaml only fills the docker cache. It pushes to no registry.
- reproducible.yaml uploads and downloads artifacts inside one run.

The actions cache and the artifact actions use the runtime token, not
GITHUB_TOKEN, so contents: read is enough for them.
@yhabib
yhabib requested a review from a team as a code owner September 4, 2026 23:39
@zeropath-ai

zeropath-ai Bot commented Sep 4, 2026

Copy link
Copy Markdown

No security or compliance issues detected. Reviewed everything up to b8bd621.

Security Overview
Detected Code Changes
Change Type Relevant files
Configuration changes ► .github/workflows/deploy-to-app.yaml
    Add permissions: contents: read
► .github/workflows/docker-main.yaml
    Add permissions: contents: read
► .github/workflows/reproducible.yaml
    Add permissions: contents: read
► .github/workflows/update-aggregator.yml
    Add permissions: contents: read
► .github/workflows/update-didc.yml
    Add permissions: contents: read
► .github/workflows/update-ic-cargo-deps.yaml
    Add permissions: contents: read
► .github/workflows/update-next.yml
    Add permissions: contents: read
► .github/workflows/update-rust.yml
    Add permissions: contents: read
► .github/workflows/update-sns-aggregator-response.yml
    Add permissions: contents: read
► .github/workflows/update-snsdemo.yml
    Add permissions: contents: read
Enhancement ► .github/workflows/deploy-to-app.yaml
    Introduce permissions: contents: read for deployment workflow
► .github/workflows/docker-main.yaml
    Introduce permissions: contents: read for docker cache workflow
► .github/workflows/reproducible.yaml
    Introduce permissions: contents: read for reproducible builds
► .github/workflows/update-aggregator.yml
    Introduce permissions: contents: read for updater workflow
► .github/workflows/update-didc.yml
    Introduce permissions: contents: read for didc updates
► .github/workflows/update-ic-cargo-deps.yaml
    Introduce permissions: contents: read for IC cargo deps updates
► .github/workflows/update-next.yml
    Introduce permissions: contents: read for next npm updates
► .github/workflows/update-rust.yml
    Introduce permissions: contents: read for rust updates
► .github/workflows/update-sns-aggregator-response.yml
    Introduce permissions: contents: read for SNS aggregator response update
► .github/workflows/update-snsdemo.yml
    Introduce permissions: contents: read for SNS demo updates

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approved

The change is a straightforward least-privilege tightening to contents: read and the reviewed workflows’ write operations are already performed using non-GITHUB_TOKEN credentials (e.g., GitHub App tokens) or runner-scoped artifact/cache mechanisms.

Pull request overview

This PR reduces the default GITHUB_TOKEN privileges across ten GitHub Actions workflows by explicitly setting workflow-level permissions to contents: read, aligning the token scope with the stated read-only usage of these jobs.

Changes:

  • Added a workflow-level permissions: block (contents: read) to ten workflows that previously relied on the repo default token permissions.
  • Ensured jobs continue to run without job-level permission overrides (workflow-level permissions apply uniformly).
File summaries
File Description
.github/workflows/update-snsdemo.yml Sets workflow GITHUB_TOKEN to contents: read while PR creation continues via GitHub App token.
.github/workflows/update-sns-aggregator-response.yml Limits default token to contents: read; PR creation remains via GitHub App token.
.github/workflows/update-rust.yml Limits default token to contents: read; PR creation remains via GitHub App token.
.github/workflows/update-next.yml Limits default token to contents: read; PR creation remains via GitHub App token.
.github/workflows/update-ic-cargo-deps.yaml Limits default token to contents: read; PR creation remains via GitHub App token.
.github/workflows/update-didc.yml Limits default token to contents: read; PR creation remains via GitHub App token.
.github/workflows/update-aggregator.yml Limits default token to contents: read; PR creation remains via GitHub App token.
.github/workflows/reproducible.yaml Limits default token to contents: read for reproducible build + artifact flow.
.github/workflows/docker-main.yaml Limits default token to contents: read for docker buildx cache population.
.github/workflows/deploy-to-app.yaml Limits default token to contents: read for the app deployment workflow.
Review details
  • Files reviewed: 10/10 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants