agentleFS
SecurityMindedSolutionsSecurityMindedSolutions/ai-skills/skills/vulnerability-management/github-remediate-vulns/SKILL.md

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

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
  1. Very specific:

    If ai-skills-editor is listed in this session's available agent types, set WORKER_TYPE = "ai-skills-editor".

    line 56
  2. Distinctive:

    Not installed: show the user the shipped file, then ask.

    line 67
  3. Distinctive:

    Ask with AskUserQuestion: Install (recommended) / Not now / Don't ask again.

    line 70
  4. Very specific:

    Don't ask again: touch ~/.claude/.ai-skills-workers-declined.

    line 73
  5. Very specific:

    Not inside a git repo, so scan immediate subfolders for .git directories

    line 100
  6. Distinctive:

    STOP and wait for user confirmation: before proceeding

    line 104
  7. Distinctive:

    If repo also provided, scope to that single repo

    line 108
  8. Distinctive:

    Run these checks before proceeding:

    line 114
  9. Very specific:

    If authentication fails, tell the user to run gh auth login.

    line 127
  10. Very specific:

    If org access fails, tell the user they may need read:org scope.

    line 128
  11. Distinctive:

    Read the module files for classification logic:

    line 197
  12. Very specific:

    Severity filtering: Only include alerts matching the --severity filter.

    line 210
  13. Very specific:

    Read the scan report template from {skill_dir}/templates/scan-report.md and fill it in.

    line 214
  14. Very specific:

    If --dry-run was specified, present the scan report and stop here.

    line 222
  15. Very specific:

    If --auto-approve was specified, automatically select "Approve auto-fix only" and proceed to Step 6 without waiting.

    line 224
  16. Distinctive:

    Approve auto-fix only: - Only apply auto-fixes, skip assisted

    line 230
  17. Distinctive:

    Dismissal handling: If the user wants to dismiss alerts:

    line 235
  18. Very specific:

    Use the --branch-prefix value (default: remediate/vulns) for branch naming.

    line 250
  19. Very specific:

    If found, warn the user and ask: continue on existing branch, create new branch with suffix, or skip this repo.

    line 276
  20. Distinctive:

    Run tests after each fix (or group of related fixes)

    line 298
  21. Distinctive:

    Pre-flight: Before applying fixes, run the test suite on the clean branch.

    line 311
  22. Very specific:

    Read the remediation report template from {skill_dir}/templates/remediation-report.md and fill it in.

    line 315
  23. Very specific:

    If --auto-approve --push were both specified, automatically select "Create PRs" and proceed without waiting.

    line 323
  24. Distinctive:

    CI/CD awareness: After creating PRs, if the repo has GitHub Actions:

    line 367
  25. Distinctive:

    Post-push alert verification: When fixes are pushed directly to main (not via PR), Dependabot needs time to detect the patched versions and …

    line 374
  26. Very specific:

    Wait 5 seconds, then check each targeted alert: gh api "/repos/{org}/{repo}/dependabot/alerts/{number}" --jq '.state'

    line 375
  27. Distinctive:

    If any alerts are still open, wait another 5 seconds and check again

    line 376
  28. Very specific:

    If the number of repos with alerts exceeds --max-repos:

    line 382
  29. Distinctive:

    After batch completes, ask: "Processed {N}/{total} repos.

    line 385

≈ “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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

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 name
  • repo: 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 + push

Execution 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.

  1. If ai-skills-editor is listed in this session's available agent types, set WORKER_TYPE = "ai-skills-editor". Otherwise set WORKER_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.
  2. 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-approve or --dry-run is set, and never ask if ~/.claude/.ai-skills-workers-declined exists. 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.
  3. 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.

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-run flag is present
  • Whether --auto-approve flag is present
  • Whether --push flag is present (requires --auto-approve)
  • --max-repos limit (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 .git directories
  • 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/null

If 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-vulns

For 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/null

The --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
done

Include 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-Remaining header, 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)"
done

Step 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:

CategoryCriteriaAction
AUTO-FIXDependabot with patched version available, patch or minor version bump onlyBump version + run tests
ASSISTED-FIXCode scanning with known fix pattern, OR major version bumps, OR repo has no test suiteAttempt fix + run tests, flag for extra review
MANUALSecret scanning alerts, no patched version available, unknown code scanning rulesReport 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:

  1. Approve all - Proceed with all auto-fix and assisted-fix items
  2. Approve auto-fix only - Only apply auto-fixes, skip assisted
  3. Approve per-repo - User selects which repos to remediate
  4. Dismiss specific alerts - Mark certain alerts as false positives on GitHub
  5. 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:

  1. The repo path (local or cloned)
  2. The approved alert numbers, with the alert JSON for each, or the $WORK file path holding it from Step 3
  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
  4. 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):

  1. CLAUDE.md in the repo root for test instructions
  2. package.json scripts for test command
  3. Makefile or makefile for test targets
  4. pyproject.toml for pytest configuration
  5. pytest.ini or setup.cfg for pytest
  6. Fall back to pytest (Python) or npm 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:

  1. Create PRs (default) - Push branches and create PRs for review
  2. Push to main - Push fixes directly to main (skips PR review)
  3. 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:

  1. Wait 5 seconds, then check each targeted alert: gh api "/repos/{org}/{repo}/dependabot/alerts/{number}" --jq '.state'
  2. If any alerts are still open, wait another 5 seconds and check again
  3. Maximum 3 checks (15 seconds total). After that, report any still-open alerts and note they may close on a subsequent GitHub scan cycle
  4. Report which alerts auto-closed and which remain open

Batching for Large Orgs

If the number of repos with alerts exceeds --max-repos:

  1. Sort repos by total alert count (highest first)
  2. Process the first batch
  3. After batch completes, ask: "Processed {N}/{total} repos. Continue to next batch?"
  4. Repeat until all repos processed or user stops

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.