Skip to content

ci: declare workflow-level contents: read on 16 build/regen workflows - #2584

Merged
Perksey merged 2 commits into
dotnet:mainfrom
arpitjain099:chore/declare-workflow-perms-readonly
Jul 26, 2026
Merged

ci: declare workflow-level contents: read on 16 build/regen workflows#2584
Perksey merged 2 commits into
dotnet:mainfrom
arpitjain099:chore/declare-workflow-perms-readonly

Conversation

@arpitjain099

Copy link
Copy Markdown
Contributor

Pins the default GITHUB_TOKEN to contents: read on every workflow in .github/workflows/. They are all native-library binding regen workflows (angle, assimp, dxvk, glfw, moltenvk, openal-soft, sdl2, shaderc, spirv-cross, spirv-reflect, swiftshader, vkd3d, vulkan-loader, wgpu) plus bindings-regeneration and codeowners checks. None of them call a GitHub API beyond the initial checkout.

Why

CVE-2025-30066 (March 2025 tj-actions/changed-files supply-chain compromise) exfiltrated GITHUB_TOKEN from workflow logs. Pinning per workflow caps runtime authority irrespective of the repo or org default, gives drift protection if the default ever widens, and is credited per-file by the OpenSSF Scorecard Token-Permissions check.

YAML validated locally with yaml.safe_load on each touched file.

@arpitjain099

Copy link
Copy Markdown
ContributorAuthor

@dotnet-policy-service agree

@Perksey

Copy link
Copy Markdown
Member

Pretty sure these workflows make use of write permissions (to push the regenerated bindings)

@arpitjain099

Copy link
Copy Markdown
ContributorAuthor

Good thing to check, and you're right that these workflows do push the regenerated bindings. I looked at how they authenticate that push, though, and it doesn't go through the default GITHUB_TOKEN:

  • Each workflow runs actions/checkout@v2 with token: ${{ secrets.PUSHABLE_GITHUB_TOKEN }}, so the persisted git credential is that PAT, and the later push from the nuke build uses it (angle.yml:36, bindings-regeneration.yml:19, sdl2.yml:41, etc).
  • The build/regen step that does the actual push gets the PAT via env: PUSHABLE_GITHUB_TOKEN, not the default token.

A workflow-level permissions: block only scopes the default GITHUB_TOKEN. Since none of these 16 use the default token for anything, contents: read doesn't touch the bindings-push path; it just shrinks the default token's blast radius if one of the build actions were ever compromised (the CVE-2025-30066 supply-chain case). These run on push with a powerful PAT in scope, so tightening the ambient token is worthwhile.

I deliberately left build.yml out of this PR for exactly the reason you raised: it's the one that uses secrets.GITHUB_TOKEN directly (PushToNuGet to GitHub Packages at build.yml:81), so it genuinely needs packages: write and isn't a contents: read candidate.

Happy to walk through any specific file if you'd like, or drop any you're not comfortable with.

Pins the default GITHUB_TOKEN to contents: read on every workflow in
.github/workflows/. They are all native-library binding regen
workflows (angle, assimp, dxvk, glfw, moltenvk, openal-soft, sdl2,
shaderc, spirv-cross, spirv-reflect, swiftshader, vkd3d,
vulkan-loader, wgpu) plus bindings-regeneration and codeowners checks.
None call a GitHub API beyond the initial checkout.
Motivation: CVE-2025-30066 (March 2025 tj-actions/changed-files
compromise) exfiltrated GITHUB_TOKEN from workflow logs. Per-workflow
caps bound runtime authority irrespective of repo or org default,
give drift protection if the default ever widens, and are credited
per-file by the OpenSSF Scorecard Token-Permissions check.
YAML validated locally with yaml.safe_load.
Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
@arpitjain099
arpitjain099force-pushed the chore/declare-workflow-perms-readonly branch from d22ff41 to 9ba99d7CompareJune 10, 2026 07:35

@PerkseyPerksey left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hmmmm, okay I'll merge but I'm not happy with the AI-generated explanation, however accurate it may be. Would appreciate human words next time.

@Perksey
Perksey enabled auto-merge (squash) July 26, 2026 16:58
@Perksey
Perksey disabled auto-merge July 26, 2026 17:00
@Perksey
Perksey enabled auto-merge (squash) July 26, 2026 17:05
@Perksey
Perksey merged commit 9b54298 into dotnet:mainJul 26, 2026
3 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants

@arpitjain099@Perksey