github-remediate-vulns
Skill2 starsChanged 42 days agoMITView on GitHub
Scan GitHub org for Dependabot, code scanning, and secret scanning alerts. Classify findings as auto-fixable, assisted, or manual. Apply fixes with test validation, then create PRs on approval. Use this skill whenever the user wants to fix vulnerabilities, remediate security alerts, patch dependencies, or triage GitHub security findings across one or many repos.
- Commits and pushes
In this repository16 other files it gives its agents.
- audit-backendSkill
- audit-frontendSkill
- audit-securitySkill
- ralph-loopSkill
- ralph-planSkill
- againSkill
- elimSkill
- huhSkill
- ughSkill
- code-audit-jevSkill
- jev-email-analysisSkill
- prompt-injection-evalSkill
- resume-mirror-evalSkill
- run-jevSkill
- traffic-triage-evalSkill
- built-withSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
29 rules. About 0 are common, 14 are distinctive, and 15 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈14
Distinctive · estimate
This author's own choices. Worth a look.
15
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 56
If ai-skills-editor is listed in this session's available agent types, set WORKER_TYPE = "ai-skills-editor".
- Distinctive: line 67
Not installed: show the user the shipped file, then ask.
- Distinctive: line 70
Ask with AskUserQuestion: Install (recommended) / Not now / Don't ask again.
- Very specific: line 73
Don't ask again: touch ~/.claude/.ai-skills-workers-declined.
- Very specific: line 100
Not inside a git repo, so scan immediate subfolders for .git directories
- Distinctive: line 104
STOP and wait for user confirmation: before proceeding
- Distinctive: line 108
If repo also provided, scope to that single repo
- Distinctive: line 114
Run these checks before proceeding:
- Very specific: line 127
If authentication fails, tell the user to run gh auth login.
- Very specific: line 128
If org access fails, tell the user they may need read:org scope.
- Distinctive: line 197
Read the module files for classification logic:
- Very specific: line 210
Severity filtering: Only include alerts matching the --severity filter.
- Very specific: line 214
Read the scan report template from {skill_dir}/templates/scan-report.md and fill it in.
- Very specific: line 222
If --dry-run was specified, present the scan report and stop here.
- Very specific: line 224
If --auto-approve was specified, automatically select "Approve auto-fix only" and proceed to Step 6 without waiting.
- Distinctive: line 230
Approve auto-fix only: - Only apply auto-fixes, skip assisted
- Distinctive: line 235
Dismissal handling: If the user wants to dismiss alerts:
- Very specific: line 250
Use the --branch-prefix value (default: remediate/vulns) for branch naming.
- Very specific: line 276
If found, warn the user and ask: continue on existing branch, create new branch with suffix, or skip this repo.
- Distinctive: line 298
Run tests after each fix (or group of related fixes)
- Distinctive: line 311
Pre-flight: Before applying fixes, run the test suite on the clean branch.
- Very specific: line 315
Read the remediation report template from {skill_dir}/templates/remediation-report.md and fill it in.
- Very specific: line 323
If --auto-approve --push were both specified, automatically select "Create PRs" and proceed without waiting.
- Distinctive: line 367
CI/CD awareness: After creating PRs, if the repo has GitHub Actions:
- Distinctive: line 374
Post-push alert verification: When fixes are pushed directly to main (not via PR), Dependabot needs time to detect the patched versions and …
- Very specific: line 375
Wait 5 seconds, then check each targeted alert: gh api "/repos/{org}/{repo}/dependabot/alerts/{number}" --jq '.state'
- Distinctive: line 376
If any alerts are still open, wait another 5 seconds and check again
- Very specific: line 382
If the number of repos with alerts exceeds --max-repos:
- Distinctive: line 385
After batch completes, ask: "Processed {N}/{total} repos.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
GitHub Vulnerability Remediation Orchestrator
You are a vulnerability remediation orchestrator. Your job is to scan a GitHub org (or single repo) for security alerts, classify what can be auto-fixed, apply fixes with test validation, and present results for user approval before pushing.
Usage: /github-remediate-vulns [org] [repo] [flags]
Arguments (all optional):
org: GitHub organization namerepo: Specific repository (requires org)--severity: Comma-separated severity filter (default:critical,high,medium,low)--alert-type: Comma-separated alert types to scan:dependabot,code-scanning,secret-scanning(default: all three)--dry-run: Scan and classify only, skip remediation--auto-approve: Skip Safety Gate 1 and auto-approve all auto-fix items only (assisted and manual still reported). Useful for CI/CD pipelines. Does NOT skip Safety Gate 2 (push approval) unless combined with--push.--push: Auto-push and create PRs after remediation (only works with--auto-approve)--max-repos N: Maximum repos to process per batch (default: 50)--branch-prefix: Custom branch prefix (default:remediate/vulns)
Examples:
/github-remediate-vulns → auto-detect context
/github-remediate-vulns SecurityMindedSolutions → scan entire org
/github-remediate-vulns SecurityMindedSolutions my-repo → scan single repo
/github-remediate-vulns --dry-run → scan only, no fixes
/github-remediate-vulns --severity critical,high,medium → exclude low severity
/github-remediate-vulns --alert-type dependabot → only Dependabot alerts
/github-remediate-vulns --alert-type code-scanning,secret-scanning → skip Dependabot
/github-remediate-vulns --auto-approve --push → CI mode: auto-fix + pushExecution Process
Step 0: Worker Setup
Remediation workers run as the ai-skills-editor agent type when it is installed. Compared with
general-purpose it starts with far less context: only the tools it needs (Read, Grep, Glob, Bash, Edit, Write), no
CLAUDE.md files, and a short system prompt. The definition ships with this skill at
{skill_dir}/agents/ai-skills-editor.md. Installing it is optional and the skill works the same
without it; {skill_dir} is resolved in Step 3, so resolve it now if needed.
- If
ai-skills-editoris listed in this session's available agent types, setWORKER_TYPE = "ai-skills-editor". Otherwise setWORKER_TYPE = "general-purpose". Either way this run continues; agent definitions load when a session starts, so an install made now applies from the next session. - Offer an install or update only when a person is answering in this session. Never ask in
claude -p, CI, a scheduled or autonomous run, or when--auto-approveor--dry-runis set, and never ask if~/.claude/.ai-skills-workers-declinedexists. Compare the shipped file with the installed one:grep -m1 '^version:' "{skill_dir}/agents/ai-skills-editor.md" grep -m1 '^version:' ~/.claude/agents/ai-skills-editor.md 2>/dev/null- Not installed: show the user the shipped file, then ask.
- Installed with a lower version: show
diff ~/.claude/agents/ai-skills-editor.md "{skill_dir}/agents/ai-skills-editor.md", then ask. - Installed with the same or a higher version: nothing to ask.
- Ask with AskUserQuestion: Install (recommended) / Not now / Don't ask again.
- Install:
mkdir -p ~/.claude/agents && cp "{skill_dir}/agents/ai-skills-editor.md" ~/.claude/agents/, then tell the user it takes effect from their next session. - Don't ask again:
touch ~/.claude/.ai-skills-workers-declined. - Not now: continue.
- Install:
Step 1: Parse Arguments & Detect Context
Parse the user's input to determine:
- Organization and repo scope
- Severity filter (default:
critical,high,medium,low) - Alert type filter (default:
dependabot,code-scanning,secret-scanning) - Whether
--dry-runflag is present - Whether
--auto-approveflag is present - Whether
--pushflag is present (requires--auto-approve) --max-reposlimit (default: 50)--branch-prefix(default:remediate/vulns)
Context Detection (when no org/repo provided):
Mode A: Inside a git repo
git rev-parse --is-inside-work-tree 2>/dev/null
git remote get-url origin 2>/dev/null- Extract org/repo from the remote URL (handles both HTTPS and SSH formats)
- Scope: single repo only
- Work directly in the repo on a new branch
Mode B: Directory with multiple repo subfolders
- Not inside a git repo, so scan immediate subfolders for
.gitdirectories - For each subfolder with a git remote, extract org/repo
- Filter to repos belonging to the authenticated org
- Present the list: "Found N repos in subfolders belonging to {org}. Remediate all?"
- STOP and wait for user confirmation before proceeding
Mode C: Explicit org argument
- Org name provided as argument
- If repo also provided, scope to that single repo
- Otherwise enumerate all repos via API
- Clone to
/tmp/github-remediate-vulns/{org}/{repo}/as needed (shallow clone)
Step 2: Validate Access
Run these checks before proceeding:
# Verify gh CLI is authenticated
gh auth status
# Confirm org access
gh api /user/orgs --jq '.[].login'
# Verify Dependabot alerts are accessible for at least one repo
gh api /repos/{org}/{first_repo}/dependabot/alerts?per_page=1 2>/dev/nullIf authentication fails, tell the user to run gh auth login.
If org access fails, tell the user they may need read:org scope.
Step 3: Scan - Fetch Vulnerability Data
Resolve the skill directory:
echo $HOME/.claude/skills/github-remediate-vulnsFor each repo in scope, fetch alerts using gh api directly from this session; this step needs no sub-agents. Only fetch alert types included in the --alert-type filter (default: all three).
Per-repo API calls (use --paginate to handle repos with 100+ alerts):
# Dependabot alerts (skip if --alert-type excludes dependabot)
gh api "/repos/{org}/{repo}/dependabot/alerts?state=open&per_page=100" --paginate 2>/dev/null
# Code scanning alerts (skip if --alert-type excludes code-scanning)
gh api "/repos/{org}/{repo}/code-scanning/alerts?state=open&per_page=100" --paginate 2>/dev/null
# Secret scanning alerts (skip if --alert-type excludes secret-scanning)
gh api "/repos/{org}/{repo}/secret-scanning/alerts?state=open&per_page=100&hide_secret=true" --paginate 2>/dev/nullThe --paginate flag is important because gh api only returns one page by default. Without it, repos with more than 100 open alerts silently lose the rest.
GitHub API quirk - missing alerts: The Dependabot list endpoint sometimes silently omits open alerts (observed with packages that have multiple related advisories, e.g. two CVEs for the same package). These alerts show as "open" when fetched individually but never appear in the list response. To catch them, cross-reference the API results with the local package manager audit:
# npm/Node.js repos - run in the repo directory
npm audit --json 2>/dev/null | jq -r '.vulnerabilities | to_entries[] | "\(.key) \(.value.severity)"'
# Python repos
pip-audit --format json 2>/dev/null | jq -r '.[] | "\(.name) \(.vulns[].id)"'Compare audit output against the GitHub API results. Any package flagged by the local audit but missing from the API list should be looked up individually:
# Look up alerts for a specific package by name
gh api "/repos/{org}/{repo}/dependabot/alerts?state=open&per_page=100" --paginate \
--jq '.[] | select(.dependency.package.name == "{package_name}") | {number, state, pkg: .dependency.package.name}'
# If still missing, fetch recent alert numbers by scanning the last 20
for i in $(seq 1 20); do
gh api "/repos/{org}/{repo}/dependabot/alerts/$i" --jq '{number, state, pkg: .dependency.package.name}' 2>/dev/null
doneInclude any alerts found this way in the scan report with a note: (found via local audit - missing from GitHub API list).
Error handling:
- 403 on archived repos: skip with note "archived, skipped"
- 403 on specific endpoint: skip that scan type, note "{scan_type} not enabled"
- 404: repo doesn't exist or no access, skip
- Rate limiting: respect
X-RateLimit-Remainingheader, pause if low
Never pull plaintext secrets. hide_secret=true keeps the secret value out of the response. Triage needs only the type, location and dates, and a secret that lands in this session's context also lands in every prompt and report built from it.
For multi-repo scans, write each repo's responses to a work directory instead of printing them, and print only per-repo counts. One loop per alert type keeps the session's context to a count table until Step 4 reads the files it needs:
WORK="$(mktemp -d)" # reuse this path for the rest of the run
for repo in {repos}; do
gh api "/repos/{org}/$repo/dependabot/alerts?state=open&per_page=100" --paginate > "$WORK/$repo.dependabot.json" 2>/dev/null
echo "$repo dependabot $(jq length "$WORK/$repo.dependabot.json" 2>/dev/null || echo error)"
doneStep 4: Classify Each Finding
Read the module files for classification logic:
{skill_dir}/modules/dependabot.md{skill_dir}/modules/code-scanning.md{skill_dir}/modules/secret-scanning.md
Classify every alert into one of three buckets:
| Category | Criteria | Action |
| AUTO-FIX | Dependabot with patched version available, patch or minor version bump only | Bump version + run tests |
| ASSISTED-FIX | Code scanning with known fix pattern, OR major version bumps, OR repo has no test suite | Attempt fix + run tests, flag for extra review |
| MANUAL | Secret scanning alerts, no patched version available, unknown code scanning rules | Report only with guidance |
Severity filtering: Only include alerts matching the --severity filter. Default is all severities (critical,high,medium,low).
Step 5: Present Scan Report (SAFETY GATE 1)
Read the scan report template from {skill_dir}/templates/scan-report.md and fill it in.
Display the report showing:
- Findings grouped by repo, then by classification (AUTO-FIX, ASSISTED-FIX, MANUAL)
- For each finding: severity, package/rule, current vs patched version, CVE/CWE
- Summary counts per repo and overall
- Estimated remediation actions
If --dry-run was specified, present the scan report and stop here.
If --auto-approve was specified, automatically select "Approve auto-fix only" and proceed to Step 6 without waiting. Still display the scan report so the user can see what was found. Assisted and manual items are reported but not acted on.
Otherwise, STOP HERE and wait for user approval before making ANY code changes.
Present options:
- Approve all - Proceed with all auto-fix and assisted-fix items
- Approve auto-fix only - Only apply auto-fixes, skip assisted
- Approve per-repo - User selects which repos to remediate
- Dismiss specific alerts - Mark certain alerts as false positives on GitHub
- Skip - Exit without changes (scan report is still useful)
Dismissal handling: If the user wants to dismiss alerts:
# Dependabot
gh api -X PATCH "/repos/{org}/{repo}/dependabot/alerts/{number}" -f state=dismissed -f dismissed_reason="{reason}" -f dismissed_comment="{comment}"
# Code scanning
gh api -X PATCH "/repos/{org}/{repo}/code-scanning/alerts/{number}" -f state=dismissed -f dismissed_reason="{reason}" -f dismissed_comment="{comment}"Valid reasons for Dependabot: fix_started, inaccurate, no_bandwidth, not_used, tolerable_risk
Valid reasons for code scanning: false positive, won't fix, used in tests
Step 6: Prepare Working Copies & Branch
Based on the detected mode:
Use the --branch-prefix value (default: remediate/vulns) for branch naming. The full branch name is {prefix}-{YYYY-MM-DD}.
Mode A (single repo, already local):
git checkout -b {prefix}-{YYYY-MM-DD}Mode B (subfolder repos, already local):
# For each approved repo
cd {repo_path}
git checkout -b {prefix}-{YYYY-MM-DD}Mode C (remote repos):
# Shallow clone to temp directory
git clone --depth 50 https://github.com/{org}/{repo}.git /tmp/github-remediate-vulns/{org}/{repo}
cd /tmp/github-remediate-vulns/{org}/{repo}
git checkout -b {prefix}-{YYYY-MM-DD}Before creating branches, check for existing remediation branches:
git branch -a | grep "{prefix}-"If found, warn the user and ask: continue on existing branch, create new branch with suffix, or skip this repo. If --auto-approve is set, create a new branch with -2 suffix automatically.
Step 7: Dispatch Remediation Sub-Agents
The remediation logic lives in:
{skill_dir}/modules/dependabot.md- for dependency bumps{skill_dir}/modules/code-scanning.md- for SAST finding fixes
Pass these as absolute paths and let each worker read them. Do not paste their text into prompts: you read them in Step 4 for classification, and writing them out again once per repo costs output for no gain.
Spawn one sub-agent per repo with subagent_type: "{WORKER_TYPE}" (from Step 0). Launch ALL repo agents in a SINGLE message for maximum parallelism.
Each sub-agent prompt MUST include:
- The repo path (local or cloned)
- The approved alert numbers, with the alert JSON for each, or the
$WORKfile path holding it from Step 3 - The absolute paths of the relevant module files (dependabot.md and/or code-scanning.md), with the instruction to read them in full before changing anything; they are binding instructions for the task
- This exact tool instruction: "Use Glob (not find/ls), Grep (not grep/rg), and Read (not cat/head/tail) tools for all file operations. Only use Bash for commands that require shell execution (git, npm, pytest, etc.)."
Sub-agent responsibilities:
- Apply fixes per the module instructions
- Run tests after each fix (or group of related fixes)
- Revert any fix that causes test failures
- Track what succeeded and what failed
- Return a structured result:
{fixed: [...], failed: [...], skipped: [...]}
Test suite detection (sub-agents should check, in order):
CLAUDE.mdin the repo root for test instructionspackage.jsonscripts fortestcommandMakefileormakefilefor test targetspyproject.tomlfor pytest configurationpytest.iniorsetup.cfgfor pytest- Fall back to
pytest(Python) ornpm test(Node.js) based on ecosystem
Pre-flight: Before applying fixes, run the test suite on the clean branch. If tests fail on the clean branch, skip that repo and note "pre-existing test failures."
Step 8: Present Results (SAFETY GATE 2)
Read the remediation report template from {skill_dir}/templates/remediation-report.md and fill it in.
Display the report showing:
- What was successfully fixed (with file paths and version changes)
- What failed tests and was reverted
- What was classified as manual (with guidance)
- Summary of branches created
If --auto-approve --push were both specified, automatically select "Create PRs" and proceed without waiting. Still display the remediation report.
Otherwise, STOP HERE and wait for user approval before pushing or creating PRs.
Present options:
- Create PRs (default) - Push branches and create PRs for review
- Push to main - Push fixes directly to main (skips PR review)
- Review changes first - Show diffs before deciding
On approval:
# For each approved repo
git add -A
git commit -m "$(cat <<'EOF'
fix: remediate security vulnerabilities
- {list of fixes applied}
Automated remediation via github-remediate-vulns skill.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
EOF
)"
git push -u origin remediate/vulns-{YYYY-MM-DD}
# Create PR
gh pr create --title "fix: remediate {N} security vulnerabilities" --body "$(cat <<'EOF'
## Summary
{summary of fixes}
## Changes
{list of changes per alert}
## Test Results
All fixes validated against the repo's test suite. Fixes that failed tests were reverted.
## Remaining Manual Items
{list of manual items if any}
🤖 Generated with [Claude Code](https://claude.com/claude-code)
EOF
)"CI/CD awareness: After creating PRs, if the repo has GitHub Actions:
# Check for CI workflows
gh pr checks {pr-number} --repo {org}/{repo}Note CI status in the final summary.
Post-push alert verification: When fixes are pushed directly to main (not via PR), Dependabot needs time to detect the patched versions and auto-close alerts. After pushing:
- Wait 5 seconds, then check each targeted alert:
gh api "/repos/{org}/{repo}/dependabot/alerts/{number}" --jq '.state' - If any alerts are still open, wait another 5 seconds and check again
- Maximum 3 checks (15 seconds total). After that, report any still-open alerts and note they may close on a subsequent GitHub scan cycle
- Report which alerts auto-closed and which remain open
Batching for Large Orgs
If the number of repos with alerts exceeds --max-repos:
- Sort repos by total alert count (highest first)
- Process the first batch
- After batch completes, ask: "Processed {N}/{total} repos. Continue to next batch?"
- Repeat until all repos processed or user stops
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

