# Dependabot Security Plan

> Fetches open Dependabot security alerts for any GitHub repository (user-specified or from workspace remote), filters Critical and High (optionally Moderate) alerts with an available patch version, and builds a Plan-mode plan with one todo per actionable fix. Use when the user asks for a Dependabot security fix plan, vulnerability remediation plan, or points at /security/dependabot (e.g. github.com/{owner}/{repo}/security/dependabot).

- Skill: `frankhildebrandt/dependabot-security-plan` (Agent Skill)
- Install (CLI): `npx skillmds@latest add frankhildebrandt/dependabot-security-plan`
- Raw SKILL.md: https://api.skillmd.com/api/skills/frankhildebrandt/dependabot-security-plan/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: frankhildebrandt (https://skillmd.com/u/frankhildebrandt)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/frankhildebrandt/dependabot-security-plan

---


# Dependabot Security Plan

Build a remediation **plan** from GitHub Dependabot security alerts. Each actionable fix becomes its own todo. Do **not** apply fixes unless the user asks after reviewing the plan.

Use `gh` for all GitHub operations.

## Severity filter

| User request | Include severities |
|--------------|-------------------|
| Default | `critical`, `high` |
| Also moderate / „auch moderate“ / `+moderate` | `critical`, `high`, `medium` |

GitHub API uses `medium` for Moderate. Ignore `low` unless the user explicitly asks for it.

## Workflow

```
Dependabot Security Plan:
- [ ] 1. Resolve target repository
- [ ] 2. Fetch and filter open alerts
- [ ] 3. Keep only actionable fixes
- [ ] 4. Group and deduplicate
- [ ] 5. Investigate fix path per group
- [ ] 6. Build Plan with one todo per fix
```

### Step 1: Resolve target repository

Determine `{owner}/{repo}` for the GitHub repository under review. This skill has **no default repository** — always resolve it at runtime.

Resolution order:

1. **Explicit input from the user** — any of:
   - `owner/repo` shorthand (e.g. `acme/widget`)
   - Full GitHub URL (e.g. `https://github.com/acme/widget`)
   - Dependabot security page URL (e.g. `https://github.com/acme/widget/security/dependabot`)
2. **Current workspace** — if the user does not name a repo, parse `{owner}/{repo}` from `git remote get-url origin` in the open workspace.

If ambiguous (multiple remotes, unclear shorthand, or no git remote), ask once. Do not guess across remotes or assume a repository from prior context.

### Step 2: Fetch open alerts

```bash
gh api "repos/{owner}/{repo}/dependabot/alerts" --paginate \
  -q '.[] | select(.state=="open") | {
    number,
    severity: .security_advisory.severity,
    summary: .security_advisory.summary,
    ghsa: .security_advisory.ghsa_id,
    package: .security_vulnerability.package.name,
    ecosystem: .security_vulnerability.package.ecosystem,
    vulnerable: .security_vulnerability.vulnerable_version_range,
    first_patched: .security_vulnerability.first_patched_version.identifier,
    manifest: .dependency.manifest_path,
    relationship: .dependency.relationship,
    scope: .dependency.scope,
    url: .html_url
  }'
```

If `gh` returns 403/404, report missing `security_events` or `dependabot_alerts` permission and stop.

### Step 3: Keep only actionable fixes

Include an alert only when **all** of the following hold:

- Severity is in the active filter (Step 1 table).
- `first_patched` is not null (Dependabot reports a patched version).
- State is `open`.

Collect alerts **without** a patch (`first_patched == null`) into a separate **„No automated fix“** list in the plan — no todo for those.

### Step 4: Group and deduplicate

Multiple alerts can refer to the same dependency in the same manifest. **One todo per group**, not per alert number.

Group key: `(manifest, ecosystem, package)`.

Per group, retain:

- All alert numbers and URLs
- Highest required `first_patched` version (prefer semver comparison; if incomparable, list each distinct target and split into separate todos)
- Worst severity in the group
- Combined summaries (short)

### Step 5: Investigate fix path per group

Before writing todos, determine how the fix would be applied. Check in the target repo (clone, existing workspace, or `gh`):

| Ecosystem | Typical fix path |
|-----------|------------------|
| npm | Direct dep → bump in `package.json`; transitive → `npm update <parent>` / override / lockfile refresh; note manifest path |
| Go | `go get -u` / replace directive / migrate off abandoned module |
| Maven, NuGet, pip, etc. | Bump version in the manifest Dependabot names |

Also check for existing work:

```bash
gh pr list -R {owner}/{repo} --author "app/dependabot" --state open --json number,title,url
```

If an open Dependabot PR already addresses a group, reference it in that todo instead of planning manual work.

Skip groups where the installed version (from lockfile/manifest in repo) is already `>= first_patched` — mark as **likely stale alert** in the plan summary, not as a todo.

### Step 6: Build Plan with one todo per fix

Use **Plan mode** (`SwitchMode` → `plan`) when available. Otherwise present the same structure in chat.

**Plan title:** `Dependabot security fixes — {owner}/{repo}`

**Plan body template:**

```markdown
# Dependabot security fixes — {owner}/{repo}

Source: https://github.com/{owner}/{repo}/security/dependabot
Severity filter: {critical, high [, medium]}
Fetched: {date}
Actionable fixes: {N} | No patch available: {M} | Stale/skipped: {K}

## Summary

{1–3 sentences: dominant packages, ecosystems, risk overview}

## Fixes

{For each group — this section mirrors todos 1:1}

### {N}. {package} ({ecosystem}) → {target_version}

- **Severity:** {critical|high|medium}
- **Manifest:** `{manifest}` ({relationship}, {scope})
- **Alerts:** [#{num}]({url}), …
- **Advisory:** {short summary}
- **Proposed fix:** {concrete command or file change}
- **Verify:** {test / build / audit command}

## No automated fix

| Package | Severity | Alerts | Notes |
|---------|----------|--------|-------|
| … | … | … | No `first_patched_version` from Dependabot |

## Suggested order

1. Critical first, then High, then Medium
2. Direct dependencies before transitive
3. Shared base manifests before leaf packages
```

**Todos:** Create **exactly one todo per group** in Step 4 (after dedup). Todo text format:

```
Fix {package} ({ecosystem}) in {manifest}: upgrade to >={target_version} — {severity} — alerts #{numbers}
```

Use `TodoWrite` to register the same items when not in Plan mode.

## Rules

- **Repository-agnostic** — resolve `{owner}/{repo}` at runtime; never hardcode or assume a specific repository.
- **Plan only** — no version bumps, commits, or PRs unless the user confirms after the plan.
- **Actionable only** — todos require a known patched version from Dependabot.
- **One fix, one todo** — dedupe duplicate alerts; split only when the same package needs incompatible target versions.
- **German or English** — match the user’s language in the plan text; keep todo IDs/slugs ASCII.
- If zero actionable fixes remain after filtering, say so clearly and still list „No automated fix“ and stale alerts if any.

## Example invocations

| User says | Resolved repo | Severities |
|-----------|---------------|------------|
| „Dependabot security plan“ (workspace has `origin` → `acme/widget`) | `acme/widget` | `critical`, `high` |
| „Plan for `acme/widget`, include moderate“ | `acme/widget` | `critical`, `high`, `medium` |
| „https://github.com/acme/widget/security/dependabot“ | `acme/widget` | `critical`, `high` |

→ Fetch alerts for the resolved repo → filter → group → plan with todos.

