Skip to content

fix(ci): harden GitHub Actions workflows (#835) - #836

Merged
paulinebm merged 1 commit into
dependabot/github_actions/actions-2436af7829from
security/workflow-hardening/pr-835
Sep 21, 2026
Merged

paulinebm merged 1 commit into
dependabot/github_actions/actions-2436af7829from
security/workflow-hardening/pr-835

Conversation

@hf-security-analysis

@hf-security-analysis hf-security-analysis Bot commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

Automated hardening of the workflow files flagged on #835.

Warning

This narrows what the workflow can reach. Job permissions were declared in .github/workflows/build_kernel.yaml, .github/workflows/build_kernel_cpu.yaml, .github/workflows/build_kernel_macos.yaml, .github/workflows/build_kernel_rocm.yaml, .github/workflows/build_kernel_windows.yaml, .github/workflows/build_kernel_xpu.yaml, .github/workflows/check_variants.yaml, .github/workflows/lint.yml, .github/workflows/nix_checks.yml, .github/workflows/test_e2e.yaml, .github/workflows/test_extra_commands.yaml, .github/workflows/update_cache.yaml. Each job now gets only the scopes its steps were read to need — if one of them does something this could not see, it will fail on the next run. The table below says which step drove each scope.

Targets dependabot/github_actions/actions-2436af7829. Files changed, and what changed them:

  • .github/workflows/build_kernel.yaml — action pins; job permissions
  • .github/workflows/build_kernel_cpu.yaml — action pins; job permissions
  • .github/workflows/build_kernel_macos.yaml — job permissions
  • .github/workflows/build_kernel_rocm.yaml — action pins; job permissions
  • .github/workflows/build_kernel_windows.yaml — job permissions
  • .github/workflows/build_kernel_xpu.yaml — action pins; job permissions
  • .github/workflows/check_variants.yaml — job permissions
  • .github/workflows/lint.yml — job permissions
  • .github/workflows/nix_checks.yml — action pins; job permissions
  • .github/workflows/publish_kernels.yml — action pins
  • .github/workflows/test_e2e.yaml — action pins; job permissions
  • .github/workflows/test_extra_commands.yaml — action pins; job permissions
  • .github/workflows/update_cache.yaml — action pins; job permissions

Fixed by this PR:

  • HIGH unpinned-action (pinact) — .github/workflows/build_kernel.yaml:31
  • HIGH unpinned-action (pinact) — .github/workflows/build_kernel_cpu.yaml:24
  • HIGH unpinned-action (pinact) — .github/workflows/build_kernel_rocm.yaml:24
  • HIGH unpinned-action (pinact) — .github/workflows/build_kernel_xpu.yaml:24
  • HIGH unpinned-action (pinact) — .github/workflows/nix_checks.yml:24
  • HIGH unpinned-action (pinact) — .github/workflows/publish_kernels.yml:251
  • HIGH unpinned-action (pinact) — .github/workflows/publish_kernels.yml:323
  • HIGH unpinned-action (pinact) — .github/workflows/test_e2e.yaml:37
  • HIGH unpinned-action (pinact) — .github/workflows/test_extra_commands.yaml:23
  • HIGH unpinned-action (pinact) — .github/workflows/update_cache.yaml:25
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/build_kernel.yaml:1
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/build_kernel.yaml:18
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/build_kernel.yaml:69
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/build_kernel_cpu.yaml:1
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/build_kernel_cpu.yaml:18
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/build_kernel_macos.yaml:1
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/build_kernel_macos.yaml:18
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/build_kernel_rocm.yaml:1
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/build_kernel_rocm.yaml:18
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/build_kernel_windows.yaml:1
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/build_kernel_windows.yaml:18
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/build_kernel_xpu.yaml:1
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/build_kernel_xpu.yaml:18
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/check_variants.yaml:1
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/check_variants.yaml:18
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/lint.yml:1
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/lint.yml:18
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/lint.yml:35
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/lint.yml:51
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/nix_checks.yml:1
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/nix_checks.yml:18
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/test_e2e.yaml:1
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/test_e2e.yaml:29
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/test_e2e.yaml:111
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/test_e2e.yaml:155
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/test_extra_commands.yaml:1
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/test_extra_commands.yaml:18
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/update_cache.yaml:1
  • MEDIUM excessive-permissions (zizmor) — .github/workflows/update_cache.yaml:12

This does not fix everything. 10 further finding(s) (2 critical, 1 high, 7 medium) need a decision this bot should not make for you. They are in the security channel with their locations — deliberately not repeated here, since this repository may be public and they are not fixed yet.

Permissions

.github/workflows/build_documentation.yaml

build was left as it is — This job only calls the external reusable workflow huggingface/doc-builder/.github/workflows/build_main_documentation.yml, whose jobs and steps are not in this file, so the token scopes it requires cannot be determined here.

.github/workflows/build_kernel.yaml

job granted why
build contents: read actions/checkout needs contents: read; the nix-installer, cachix (authenticated via a secret, not the GITHUB_TOKEN) and upload-artifact steps in the same run require no token scopes.
test contents: read actions/checkout needs contents: read; download-artifact pulls an artifact produced by the build job in the same run, and the docker build/run steps use no GitHub API.

.github/workflows/build_kernel_cpu.yaml

job granted why
build contents: read Only actions/checkout needs the token (contents: read); the nix-installer, cachix (which uses a secret, not the GITHUB_TOKEN), and the nix build/test steps make no GitHub API writes.

.github/workflows/build_kernel_macos.yaml

job granted why
build contents: read Only actions/checkout needs the token (contents: read); the Nix/Cachix steps and Metal build just compile code and the cachix auth token is a secret, not a token scope.

.github/workflows/build_kernel_rocm.yaml

job granted why
build contents: read Only actions/checkout needs the token (contents: read); the nix-installer and cachix steps authenticate via a secret, not the GITHUB_TOKEN, and the nix build steps use no API access.

.github/workflows/build_kernel_windows.yaml

job granted why
build contents: read Only actions/checkout needs the token (contents: read); the remaining steps are CUDA/Rust/Python toolchain setup, cache actions (which use the cache service, not the token) and local compilation — note the nix-builder\scripts\windows\builder.ps1 build script is not in this file, but its invocation is a plain kernel build with no API usage.

.github/workflows/build_kernel_xpu.yaml

job granted why
build contents: read Only actions/checkout needs the token (contents: read); the nix-installer, cachix (authenticated via a secret, not the GITHUB_TOKEN) and nix build steps make no GitHub API writes.

.github/workflows/build_pr_documentation.yaml

build was left as it is — This job only calls the external reusable workflow huggingface/doc-builder/.github/workflows/build_pr_documentation.yml, whose job definitions are not in this file, so the required token scopes cannot be read here.

.github/workflows/check_variants.yaml

job granted why
build contents: read Only actions/checkout needs the token (contents: read); the remaining steps run nix evaluations, git diff, and a local script (nix-builder/scripts/gen_variants_markdown.py, whose contents aren't in this file but which only regenerates a tracked markdown file for comparison) without any API calls or pushes.

.github/workflows/lint.yml

job granted why
lint contents: read Only actions/checkout plus ruff-action lint/format checks that operate on local files, so contents: read is sufficient.
griffe contents: read actions/checkout with fetch-depth: 0 and a local uvx griffe API-diff run against the main ref; no API writes, so contents: read.
validate-dependencies contents: read actions/checkout followed by a local diff of two checked-out files needs only contents: read.

.github/workflows/nix_checks.yml

job granted why
build contents: read Only actions/checkout needs the token (contents: read); the nix-installer and cachix actions authenticate via their own inputs/secrets and the remaining steps just run nix fmt/nix build locally, so no write scopes are needed.

.github/workflows/test_e2e.yaml

job granted why
init-build-upload contents: read actions/checkout needs contents: read; the nix build/upload steps push artifacts to the Hugging Face Hub using HF_TOKEN, not the GitHub token, so no write scopes are required (cachix and nix-installer actions use their own secrets).
download-and-test contents: read actions/checkout needs contents: read; setup-uv and dtolnay/rust-toolchain only download public tooling and the test step pulls the kernel from the HF Hub, requiring no GitHub token scopes.
cleanup {} — nothing No checkout and no GitHub API use — the only step deletes Hugging Face Hub repos via huggingface_hub with HF_TOKEN, so no GITHUB_TOKEN scopes are needed (setup-uv only fetches public release assets).

.github/workflows/test_extra_commands.yaml

job granted why
build contents: read actions/checkout needs contents: read; the nix-installer and cachix actions only fetch installers/binary caches (cachix uses its own auth token, not GITHUB_TOKEN), and the two nix run steps just build/test locally, so no write scopes are required.

.github/workflows/test_kernels.yaml

job granted why
build contents: read Only actions/checkout needs the token (contents: read); the test, mypy, coverage-rendering and actions/upload-artifact steps all operate on the checked-out tree within the same run, so the workflow's declared packages: write is unnecessary — the PR comment is posted by a separate downstream workflow_run workflow, not here.

.github/workflows/update_cache.yaml

job granted why
build contents: read Only actions/checkout needs the token (contents: read); the nix-installer and cachix steps authenticate to Cachix with a secret, not the GITHUB_TOKEN, and nix build just builds locally.

.github/workflows/upload_pr_documentation.yaml

build was left as it is — This job only declares uses: to call an external reusable workflow (huggingface/doc-builder/.github/workflows/upload_pr_documentation.yml) that is not in this file, so its token needs cannot be read here; based on the workflow_run trigger and comment_bot_token input it likely needs at least actions: read to fetch the triggering run's artifacts and pull-requests: write to post a docs preview comment — verify against the pinned doc-builder workflow.

Anything not listed above keeps the permissions it had. To measure a job this could not read, add GitHubSecurityLab/actions-permissions/monitor to it and run the workflow — it reports the minimum the run actually used.

Pinning changes come from pinact and are mechanical. Any other change was generated by Claude — read it before merging.

@paulinebm
paulinebm merged commit c2d5bf6 into dependabot/github_actions/actions-2436af7829 Sep 21, 2026
32 checks passed
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.

1 participant