fix(ci): harden GitHub Actions workflows (#14789) - #14825
Open
hf-security-analysis[bot] wants to merge 1 commit into
Open
hf-security-analysis[bot] wants to merge 1 commit into
hf-security-analysis[bot] wants to merge 1 commit into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Automated hardening of the workflow files flagged on #14789.
Warning
This changes when the workflow runs and what it can reach. Both triggers and permissions were rewritten in
.github/workflows/claude_review.yml,.github/workflows/issue_labeler.yml,.github/workflows/pr_labeler.yml. Read the diff before merging — either one can change what the workflow is able to do.Targets
dependabot/github_actions/actions-ca6b5df6ad. Files changed, and what changed them:.github/workflows/bot_pytest.yml— action pins; auth gate.github/workflows/claude_review.yml— action pins; job permissions.github/workflows/issue_labeler.yml— job permissions; llm injection.github/workflows/mirror_community_pipeline.yml— action pins.github/workflows/notify_slack_about_release.yml— action pins.github/workflows/pr_dependency_test.yml— action pins.github/workflows/pr_labeler.yml— job permissions; dangerous trigger.github/workflows/pr_modular_tests.yml— action pins.github/workflows/pr_test_fetcher.yml— action pins.github/workflows/pr_tests.yml— action pins.github/workflows/pr_tests_gpu.yml— action pins.github/workflows/pr_torch_dependency_test.yml— action pins.github/workflows/push_tests.yml— action pins.github/workflows/push_tests_fast.yml— action pins.github/workflows/push_tests_mps.yml— action pins.github/workflows/pypi_publish.yaml— action pins.github/workflows/release_tests_fast.yml— action pins.github/workflows/ssh-runner.yml— action pins.github/workflows/stale.yml— action pins.github/workflows/trufflehog.yml— action pins.github/workflows/update_metadata.yml— action pinsFixed by this PR:
broken_auth_gate(claude) — .github/workflows/bot_pytest.ymlunpinned-action(pinact) — .github/workflows/bot_pytest.yml:78unpinned-action(pinact) — .github/workflows/bot_pytest.yml:119excessive-permissions(zizmor) — .github/workflows/claude_review.yml:10excessive-permissions(zizmor) — .github/workflows/claude_review.yml:11unpinned-action(pinact) — .github/workflows/claude_review.yml:37llm_prompt_injection(claude) — .github/workflows/issue_labeler.ymlexcessive-permissions(zizmor) — .github/workflows/issue_labeler.yml:9unpinned-action(pinact) — .github/workflows/mirror_community_pipeline.yml:72unpinned-action(pinact) — .github/workflows/mirror_community_pipeline.yml:78unpinned-action(pinact) — .github/workflows/notify_slack_about_release.yml:16unpinned-action(pinact) — .github/workflows/notify_slack_about_release.yml:19unpinned-action(pinact) — .github/workflows/pr_dependency_test.yml:25unpinned-action(pinact) — .github/workflows/pr_dependency_test.yml:27dangerous-triggers(zizmor) — .github/workflows/pr_labeler.yml:3excessive-permissions(zizmor) — .github/workflows/pr_labeler.yml:9unpinned-action(pinact) — .github/workflows/pr_modular_tests.yml:47unpinned-action(pinact) — .github/workflows/pr_modular_tests.yml:49unpinned-action(pinact) — .github/workflows/pr_modular_tests.yml:67unpinned-action(pinact) — .github/workflows/pr_modular_tests.yml:69unpinned-action(pinact) — .github/workflows/pr_modular_tests.yml:95unpinned-action(pinact) — .github/workflows/pr_modular_tests.yml:125unpinned-action(pinact) — .github/workflows/pr_modular_tests.yml:154unpinned-action(pinact) — .github/workflows/pr_test_fetcher.yml:34unpinned-action(pinact) — .github/workflows/pr_test_fetcher.yml:48unpinned-action(pinact) — .github/workflows/pr_test_fetcher.yml:89unpinned-action(pinact) — .github/workflows/pr_test_fetcher.yml:115unpinned-action(pinact) — .github/workflows/pr_test_fetcher.yml:144unpinned-action(pinact) — .github/workflows/pr_test_fetcher.yml:170unpinned-action(pinact) — .github/workflows/pr_tests.yml:42unpinned-action(pinact) — .github/workflows/pr_tests.yml:44unpinned-action(pinact) — .github/workflows/pr_tests.yml:62unpinned-action(pinact) — .github/workflows/pr_tests.yml:64unpinned-action(pinact) — .github/workflows/pr_tests.yml:122unpinned-action(pinact) — .github/workflows/pr_tests.yml:166unpinned-action(pinact) — .github/workflows/pr_tests.yml:198unpinned-action(pinact) — .github/workflows/pr_tests.yml:226unpinned-action(pinact) — .github/workflows/pr_tests.yml:252unpinned-action(pinact) — .github/workflows/pr_tests.yml:293unpinned-action(pinact) — .github/workflows/pr_tests_gpu.yml:43unpinned-action(pinact) — .github/workflows/pr_tests_gpu.yml:45unpinned-action(pinact) — .github/workflows/pr_tests_gpu.yml:63unpinned-action(pinact) — .github/workflows/pr_tests_gpu.yml:65unpinned-action(pinact) — .github/workflows/pr_tests_gpu.yml:95unpinned-action(pinact) — .github/workflows/pr_tests_gpu.yml:113unpinned-action(pinact) — .github/workflows/pr_tests_gpu.yml:133unpinned-action(pinact) — .github/workflows/pr_tests_gpu.yml:182unpinned-action(pinact) — .github/workflows/pr_tests_gpu.yml:205unpinned-action(pinact) — .github/workflows/pr_tests_gpu.yml:251unpinned-action(pinact) — .github/workflows/pr_tests_gpu.yml:267unpinned-action(pinact) — .github/workflows/pr_tests_gpu.yml:299unpinned-action(pinact) — .github/workflows/pr_torch_dependency_test.yml:25unpinned-action(pinact) — .github/workflows/pr_torch_dependency_test.yml:27unpinned-action(pinact) — .github/workflows/push_tests.yml:40unpinned-action(pinact) — .github/workflows/push_tests.yml:58unpinned-action(pinact) — .github/workflows/push_tests.yml:78unpinned-action(pinact) — .github/workflows/push_tests.yml:109unpinned-action(pinact) — .github/workflows/push_tests.yml:131unpinned-action(pinact) — .github/workflows/push_tests.yml:166unpinned-action(pinact) — .github/workflows/push_tests.yml:183unpinned-action(pinact) — .github/workflows/push_tests.yml:209unpinned-action(pinact) — .github/workflows/push_tests.yml:226unpinned-action(pinact) — .github/workflows/push_tests.yml:251unpinned-action(pinact) — .github/workflows/push_tests.yml:267unpinned-action(pinact) — .github/workflows/push_tests.yml:298unpinned-action(pinact) — .github/workflows/push_tests_fast.yml:63unpinned-action(pinact) — .github/workflows/push_tests_fast.yml:96unpinned-action(pinact) — .github/workflows/push_tests_mps.yml:29unpinned-action(pinact) — .github/workflows/push_tests_mps.yml:71unpinned-action(pinact) — .github/workflows/pypi_publish.yaml:75unpinned-action(pinact) — .github/workflows/release_tests_fast.yml:39unpinned-action(pinact) — .github/workflows/release_tests_fast.yml:58unpinned-action(pinact) — .github/workflows/release_tests_fast.yml:78unpinned-action(pinact) — .github/workflows/release_tests_fast.yml:109unpinned-action(pinact) — .github/workflows/release_tests_fast.yml:131unpinned-action(pinact) — .github/workflows/release_tests_fast.yml:166unpinned-action(pinact) — .github/workflows/release_tests_fast.yml:183unpinned-action(pinact) — .github/workflows/release_tests_fast.yml:223unpinned-action(pinact) — .github/workflows/release_tests_fast.yml:240unpinned-action(pinact) — .github/workflows/release_tests_fast.yml:266unpinned-action(pinact) — .github/workflows/release_tests_fast.yml:283unpinned-action(pinact) — .github/workflows/release_tests_fast.yml:309unpinned-action(pinact) — .github/workflows/release_tests_fast.yml:326unpinned-action(pinact) — .github/workflows/release_tests_fast.yml:359unpinned-action(pinact) — .github/workflows/ssh-runner.yml:41unpinned-action(pinact) — .github/workflows/stale.yml:18unpinned-action(pinact) — .github/workflows/stale.yml:21unpinned-action(pinact) — .github/workflows/trufflehog.yml:18unpinned-action(pinact) — .github/workflows/update_metadata.yml:21This does not fix everything. 43 further finding(s) (39 high, 4 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/bot_pytest.ymlgatepull-requests: writegpucontents: readreportpull-requests: writegh api -X PATCH repos/$REPO/issues/comments/$CIDto edit the bot's comment on the PR, which requires pull-requests: write (issues: write would be the equivalent if the target were a non-PR issue)..github/workflows/claude_review.ymlclaude-reviewcontents: write,issues: read,pull-requests: writegit push origin) and runsgh pr create/gh pr comment, driving contents: write and pull-requests: write; checkout and thegh pr viewcalls only need read, and issues: read covers reading the triggering issue_comment payload — the anthropics/claude-code-action step is the one to double-check, since it posts/updates its progress comment on the PR (covered by pull-requests: write) and may want actions: read if you later let it inspect CI logs..github/workflows/codeql.yml.github/workflows/issue_labeler.ymllabelcontents: read,issues: writeactions/checkoutneeds contents: read, and the final step runsgh issue edit --add-labelwith GITHUB_TOKEN, which requires issues: write; the 'Get labels from LLM' step runs utils/label_issues.py which is not in this file, but it is only given HF_TOKEN (no GitHub token), so it should not need repository scopes — worth a quick check by the reviewer..github/workflows/pr_labeler.ymllabelcontents: read,pull-requests: writemissing-testscontents: read,pull-requests: writegh pr edit --add-label/--remove-label, requiring pull-requests: write; the helper script utils/check_test_missing.py is not in this file but only consumes piped API output on stdin, so it is the step a reviewer should double-check.fixes-issuepull-requests: writegh pr edit --add-label/--remove-labelwrites labels on the pull request, so pull-requests: write is required; no checkout is performed so no contents scope is needed.size-labelpull-requests: writegh api repos/.../pulls/Nand then adds/removes size labels withgh pr edit, which needs pull-requests: write..github/workflows/pr_link_issue_reminder.yml.github/workflows/stale.ymlclose_stale_issuescontents: read,issues: write,pull-requests: writeactions/checkoutneedscontents: read, and thepython utils/stale.pystep (a PyGithub stale bot that comments on and closes stale issues and PRs) drivesissues: writepluspull-requests: write— the script body is not in this file, so a reviewer should confirm it does not also write repository contents.Anything not listed above keeps the permissions it had. To measure a job this could not read, add
GitHubSecurityLab/actions-permissions/monitorto it and run the workflow — it reports the minimum the run actually used.Pinning changes come from
pinactand are mechanical. Any other change was generated by Claude — read it before merging.