Merged
Conversation
The github-script REST client was silently swallowing API errors (e.g. auth/permission failures), leaving has_alerts=false and causing all downstream steps to be skipped with no visible reason. Switch to gh CLI with GH_TOKEN so failures exit loudly with a clear error message. Also simplifies the code by doing the JSON filtering and reshaping in a single jq expression.
The Dependabot REST API returns 404 for GITHUB_TOKEN even with security-events: read in many org configurations. Switch to cargo audit --json which uses the same RustSec advisory database that Dependabot uses for Rust, needs no API permissions, and provides richer data (installed version, exact patched ranges, CVSS vector). Also drop the now-unnecessary security-events: read and id-token: write permissions from the job.
Replace hardcoded 'main' with github.event.repository.default_branch so the workflow works regardless of the repo's default branch name. Also add allowed_tools to grant Claude explicit permission to run Bash, Read, Write, Edit, Glob and Grep — the 12 permission denials in the previous run indicate the action was blocking tool calls without an explicit allowlist.
allowed_tools is not a valid input for claude-code-action; the correct form is claude_args with the --allowedTools flag, matching how claude-review uses it in claude.yml. The invalid key was silently ignored, leaving Claude with no tool permissions and causing 20 permission denials.
- Drop cargo audit in favour of the Dependabot alerts API, which surfaces the same vulnerabilities with severity already labelled - Pre-select the top 2 highest-risk alerts (critical > high > medium) in jq before Claude runs, removing all in-prompt budget counting - Restore security-events: read permission needed by the API - Trim the Claude prompt to the essential fix steps only - Keep show_full_output: true for debugging and prompt injection protection (alerts written to file, not interpolated)
GITHUB_TOKEN cannot access the Dependabot alerts API regardless of the security-events: read permission — GitHub maps that scope to code scanning, not Dependabot. The endpoint requires a fine-grained PAT with the 'Dependabot alerts: Read' repository permission. - Use GH_SECURITY_PAT secret for the gh api call - Fetch raw JSON to a file first, then pipe to jq — this way a gh API error is caught before jq runs (fixes the 'Cannot index string' error that followed the 404) - Add an early check that prints a clear error if the secret is unset
GitHub Actions runners automatically set GH_TOKEN=GITHUB_TOKEN for the gh CLI before any step runs. When we set GH_TOKEN via the env block with an empty or lower-priority secret, gh silently falls back to the runner's value — causing the fine-grained PAT to never be used (shows 'never used' in GitHub token settings). Fix: store the PAT as DEPENDABOT_PAT (different name, no collision) and apply it inline as GH_TOKEN=$DEPENDABOT_PAT gh api ... so the shell-level assignment takes precedence over the runner environment.
The Dependabot alerts REST API consistently returns 404 regardless of token type (GITHUB_TOKEN, fine-grained PAT) due to GitHub API access restrictions. For Rust repos this is unnecessary — cargo audit queries the identical RustSec advisory database that Dependabot uses, with no authentication required. Selects the top 2 patchable vulnerabilities by severity and writes them to /tmp/alerts.json for Claude to process.
This reverts commit 9e9bc6d.
louisliu2048
approved these changes
Mar 18, 2026
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.
Description
Fixes and hardens the
security-dependabot-fixworkflow so it reliably detects, deduplicates, and auto-patches Dependabot security alerts without creating duplicate PRs.Type of Change
Changes
Fix: use
ghCLI instead ofgithub-scriptfor alert fetchingThe
github-scriptREST client was silently swallowing API errors (e.g. auth/permission failures), leavinghas_alerts=falseand skipping all downstream steps with no visible error. Switching to theghCLI means failures exit loudly with a clear message.Fix: Dependabot alerts API requires a fine-grained PAT
GITHUB_TOKENreturns 404 on the Dependabot alerts endpoint regardless of thesecurity-events: readpermission — GitHub maps that scope to code scanning, not Dependabot. A fine-grained PAT (GH_SECURITY_PAT) with "Dependabot alerts: Read" is required. Raw JSON is now fetched to a file first so agh apierror is caught beforejqruns (fixes theCannot index stringerror that followed the 404).Fix: avoid
GH_TOKENcollision with the runner pre-set valueGitHub Actions runners automatically set
GH_TOKEN=GITHUB_TOKENfor theghCLI before any step runs. SettingGH_TOKENin the stepenvblock with the PAT was silently overridden by the runner. Fix: store the PAT as a distinctly-named env var (GH_SECURITY_PAT) and apply it inline (GH_TOKEN="$GH_SECURITY_PAT" gh api ...) so the shell-level assignment wins.Fix:
gh pr listused the wrong token for deduplicationThe existing-PR check (
gh pr list) ran underGH_SECURITY_PAT, which only has "Dependabot alerts: Read" and cannot list pull requests. The command failed silently (2>/dev/null || echo '[]'), making every alert appear unhandled on every run. Fix: useGITHUB_TOKEN(which haspull-requests: write) for the PR list call.Fix: deduplicate by package name, not alert number
The original filter extracted the alert number from the branch name (
split("-") | last) and matched it against each alert's.number. A single package can have multiple CVE alerts, and a single PR can fix all of them under one branch named after the first alert. Subsequent alerts for the same package were never matched and triggered duplicate PRs. Fix: match by package name — skip any alert whose package already has an openfix/security-<package>-*branch.Fix: use dynamic default branch
Replaced the hardcoded
mainreference with${{ github.event.repository.default_branch }}so the workflow works on repos whose default branch is not namedmain.Fix: correct
allowedToolsparameter forclaude-code-actionallowed_toolsis not a valid input forclaude-code-action; the correct form isclaude_args: "--allowedTools Bash,Read,Write,Edit,Glob,Grep". The invalid key was silently ignored, leaving Claude with no tool permissions and causing repeated permission denials.Refactor: pre-select alerts in
jqbefore Claude runsFilter to critical/high/medium severity, sort by severity rank, check for existing PRs, and write the final top-2 list to
/tmp/alerts.jsonbefore Claude is invoked. This removes all in-prompt budget logic, keeps the Claude prompt focused on fixing, and prevents prompt injection (advisory text is written to a file, never interpolated into the prompt).Checklist
docs/folder