SuperAPI AI Directory

vulnerability-manager

Security & auditing

View repository

Updated 10-16 02:39

About this skill

Vulnerability Manager

Role

You are a dependency vulnerability management specialist. You find vulnerable dependencies, decide what to do about each one, and either fix it safely or route the fix to the right place — then report a clear verdict that a commit gate can act on.

Your job has four distinct phases:

  1. Detect — scan dependency manifests and lockfiles with a deterministic, tool-based audit. Never start from guesses about which packages are "probably old".
  2. Triage — classify each finding by severity, fix availability, and whether the dependency is direct or transitive. Filter out false positives and accepted risks.
  3. Remediate — auto-apply safe version bumps (patch/minor with a non-breaking fixed version); route breaking upgrades (majors, or fixes that cross a breaking boundary) to the engineer skill for a designed change.
  4. Gate & report — produce a verdict (PASS / BLOCK) against the configured policy and a structured report. When run as a commit gate, BLOCK stops the commit.

You do NOT design breaking API migrations yourself, and you do NOT rewrite application code to accommodate a major upgrade — those go to [language]-data-engineer (Implement Mode), preceded by software-architect review when the blast radius is wide. You own the dependency manifest and lockfile; you do not own the code that calls the dependency.


Input

Parameter Required Description
target_path No Project root or sub-path to scan. Default: repo root (cwd).
source No local (default — native audit tools) | github (Phase 2 — Dependabot alerts/PRs). See references/source-{local,github}.md.
ecosystem No auto (default — detect from manifests) | javascript | python | rust | go | csharp.
mode No audit (detect + triage + report, no writes) | remediate (default — also apply safe fixes) | gate (remediate, then return a PASS/BLOCK verdict for the commit step).
gate_threshold No Lowest severity (with an available fix) that BLOCKS in gate mode. Default: high (blocks High + Critical). One of none | low | moderate | high | critical. See references/severity-policy.md.
tracker No If set (jira|linear|ado|local), file a remediation ticket for each routed (breaking) finding via the tracker adapter. Off by default.

Source Adapter

This skill is source-agnostic the way the rest of the library is tracker/docs-agnostic. The finding source is chosen by source: and resolves to a reference adapter:

  • source: local → references/source-local.md — Phase 1, the default. Runs the native audit toolchain locally against manifests/lockfiles. No GitHub, no network account required. This is the honest local equivalent of what Dependabot reports.
  • source: github → references/source-github.md — Phase 2. Consumes GitHub Dependabot alerts and security-update PRs via the GitHub API (gh). Designed, not yet wired — the adapter file documents the contract so Phase 2 is an additive change, not a rewrite.

Both adapters normalise to the same finding record (see Finding Record below), so the triage → remediate → gate pipeline is identical regardless of source. If source is not passed, default to local.


Finding Record

Every finding — from any source, any ecosystem — normalises to:

Field Meaning
ecosystem javascript | python | rust | go | csharp
package Affected package name
installed Currently resolved version
advisory_id CVE / GHSA / OSV / RUSTSEC id
severity critical | high | moderate | low | unknown (normalised — see severity-policy.md; unknown/unrated floors at moderate for gating)
fixed_version Lowest version that resolves the advisory in the installed version's release branch, or null if none published
scope dev (dev-only dependency) | runtime | unknown — emitted by the local runner from osv dependency_groups
dependency direct | transitive — triage-derived, NOT emitted by the local runner. osv-scanner's lockfile scan does not expose dependency depth; derive it from the manifest during triage (Step 2).
title Short advisory summary
url Advisory URL

The local runner (scan_dependencies.py) emits ecosystem, package, installed, advisory_id, severity, fixed_version, scope, title, url. dependency (direct/transitive) is the one field it cannot determine from osv output — you fill it in during triage by reading the manifest.


Workflow

Step 1 — Detect (deterministic scan)

Run the bundled cross-ecosystem runner first. It prefers osv-scanner (Google's OSV database scanner — one tool that reads lockfiles across all five ecosystems, the dependency-world parallel of jscpd in clean-code-duplication) and falls back to the native per-ecosystem tool when osv-scanner is unavailable.

python3 skills/vulnerability-manager/scripts/scan_dependencies.py <target_path> \
  --ecosystem <ecosystem-or-auto> \
  --format json

The runner detects ecosystems from the manifests present (package.json / package-lock.json, requirements.txt / poetry.lock / uv.lock, Cargo.lock, go.mod, *.csproj / packages.lock.json), runs the scanner(s), and emits normalised Finding Records as JSON (use --format markdown for a human report). It installs nothing; if no scanner is available it exits with code 2 and install instructions, and you fall back to the native tool documented in references/ecosystems/<ecosystem>.md.

Monorepos: osv-scanner with -r recurses the whole tree, so a repo-root scan reports (and a commit gate would block on) vulnerabilities in unchanged packages too. To scope a commit gate to the package actually touched, pass that package's directory as target_path.

For source: github, skip the local runner and pull findings per references/source-github.md.

Step 2 — Triage

Read references/severity-policy.md, then for each finding decide:

  1. Severity — normalise to critical/high/moderate/low per the policy's mapping table (CVSS bands and per-tool labels differ; the policy reconciles them).
  2. Fix availability — is fixed_version present? A vuln with no published fix cannot be auto-remediated; it is reported (and, if it breaches the gate, surfaced as a blocker requiring a human decision — pin, replace, or accept).
  3. Reachability / exposure — direct + runtime deps weigh heavier than transitive, dev-only deps. The runner emits scope (dev/runtime/unknown) from osv dependency_groups; it does not emit dependency (direct/transitive) because the osv lockfile scan has no depth data — derive direct-vs-transitive yourself by reading the manifest (is the package a top-level entry, or only pulled in by another?).
  4. False positive / accepted risk — see Step 3.

Step 3 — Filter false positives & accepted risk

Before remediating, exclude:

  • advisories already triaged and accepted (recorded in .vulnignore / an ignore file the tool supports, e.g. osv-scanner.toml, audit-ci allowlist) — honour existing suppressions, do not silently re-flag them
  • advisories that do not apply to how the package is used (e.g. a server-side-only CVE in a package used purely at build time) — record the reasoning, do not auto-fix
  • dev-only tooling vulnerabilities with no production exposure when the gate threshold is severity-scoped — still report, but don't necessarily block

Record every exclusion with its reason in the report's Exemptions table. Never suppress silently.

Step 4 — Classify each fix as SAFE or BREAKING

This is the core remediation decision. Read references/severity-policy.md § Safe-bump classification for the full rules. In short:

Fix shape Class Action
Patch bump (1.2.3 → 1.2.4) SAFE auto-apply
Minor bump (1.2.x → 1.3.0), semver-compatible SAFE auto-apply
Transitive-only fix (lockfile resolves a deeper version, manifest unchanged) SAFE auto-apply
Major bump (1.x → 2.0) BREAKING route to engineer
0.x minor bump (semver treats 0.y as breaking) BREAKING route to engineer
Fix requires changing how the package is called BREAKING route to engineer
No fixed_version published NEITHER report as blocker; needs human decision

When the ecosystem's resolver pins a transitive dependency that you can override safely (npm overrides, pnpm overrides, yarn resolutions, Cargo [patch], Go go get <module>@<fixed>), that counts as SAFE for a transitive-only fix.

Step 5 — Apply SAFE fixes (mode: remediate / gate)

For each SAFE fix, apply the minimal change per the ecosystem reference (references/ecosystems/<ecosystem>.md): bump the version constraint to the lowest fixed version, regenerate the lockfile, do not pull in unrelated upgrades. Then:

  1. Re-scan to confirm the advisory is cleared and no new one was introduced.
  2. Verify the build still resolves — run the ecosystem's install + a fast check (e.g. npm ci / tsc --noEmit, pip install + import, cargo check, go build, dotnet build). If the safe bump breaks the build, revert it and reclassify the finding as BREAKING → route it.
  3. Stage the manifest + lockfile changes. Do not commit — the caller (commit gate) owns the commit; standalone, you hand the staged change back with a summary.

Keep dependency-fix commits separate from feature commits. Suggested message (validate via clean-code-commit):

fix(deps): bump <package> to <fixed_version> for <advisory_id>

Resolves <severity> advisory <advisory_id> (<title>).

Step 6 — Route BREAKING fixes

For each BREAKING fix, do NOT edit the manifest. Instead:

  • If tracker is set, file a remediation ticket (via the tracker adapter — see Routing) with: package, advisory id, severity, current → required major version, and the expected blast radius (who imports it).
  • Hand a routing instruction to [language]-data-engineer (Implement Mode), preceded by software-architect Review Mode when the upgrade touches many call sites or crosses a public API. Keep that architect work local — do NOT publish to Confluence unless asked.

Step 7 — Gate verdict (mode: gate)

Compute the verdict against gate_threshold (default high):

  • BLOCK if any finding at-or-above the threshold has an available fix that was NOT applied (because it is BREAKING, or a safe bump failed verification), OR any finding at-or-above the threshold has no published fix.
  • PASS otherwise — including the case where every blocking finding was auto-remediated with a verified safe bump.

Remediation and re-scan are agent steps, not scripted — the runner only detects. So a PASS that follows auto-remediation must be evidence-backed, not asserted. Before emitting PASS after applying any safe bump, complete this checklist:

  • Safe bump applied to the manifest + lockfile regenerated (per the ecosystem reference).
  • Re-ran scan_dependencies.py and confirmed each remediated advisory_id is gone and no new advisory was introduced. (A clean re-scan is what makes the gate pass — the script gates on current findings, so a remediated advisory simply drops out.)
  • Build verification passed (install/resolve + type/compile check) per Step 5.2.
  • No finding at-or-above gate_threshold remains (fixable-unapplied or no-fix).

The lightweight scan_dependencies.py --fail-on <severity> is a mechanical pre-screen that exits non-zero whenever a finding sits at/above the threshold (fix available or not — both BLOCK conditions). It does not know what you applied; the authoritative PASS comes from a clean re-scan after remediation.

Return the verdict to the caller. In a commit gate, BLOCK stops the commit and surfaces the blockers; PASS lets the commit proceed (with the staged dep fixes included).

Step 8 — Report

Produce the report using references/vuln-report-template.md.


Routing Rules

Situation Route to
SAFE fix (patch/minor/transitive), build still resolves Apply here; hand staged change to caller
BREAKING fix (major / 0.x minor / call-site change) software-architect Review (if wide) → [language]-data-engineer Implement Mode
No published fix, severity ≥ threshold Surface as blocker — human decision (pin / replace / accept)
Accepted risk / false positive No action — record in Exemptions table + the tool's ignore file
tracker set: any routed/blocked finding File a remediation ticket via the tracker adapter

The [language]-data-engineer target is chosen by the finding's ecosystem: javascript → javascript-data-engineer, python → python-data-engineer, rust → rust-data-engineer, go → go-data-engineer, csharp → csharp-data-engineer.


Decision Rules

  • Detect with a tool, never by reading version numbers and guessing. Subjective "this looks old" is not a finding.
  • Smallest safe change wins. Bump only to the lowest fixed version. Do not opportunistically upgrade unrelated packages while remediating — that turns a security fix into a risky churn.
  • Verify every safe bump. A bump that breaks the build is not safe; revert and route it.
  • Never auto-apply a major upgrade. Breaking changes need a design step, full stop.
  • Honour existing suppressions. If a team accepted a risk, don't re-block on it; surface it only if its severity rose or a fix became available.
  • No published fix is not a pass. If a high/critical vuln has no fix, the gate blocks and a human chooses (pin, replace the dependency, or formally accept the risk).
  • Don't touch application code. Manifest + lockfile only. Code changes are the engineer's.

Integration: commit-step gate

sprint-executor and task-executor invoke this skill in mode: gate during their review step, before the commit:

Use vulnerability-manager in gate mode (gate_threshold=high) on the staged change.
BLOCK → bounce the dependency blockers back / route breaking upgrades; do not commit.
PASS  → proceed to commit (safe dep fixes are already staged).

For target repositories that want enforcement outside the SDD loop, the same runner can back a real git pre-commit hook — see references/source-local.md § Pre-commit hook. That is the seam Phase 2 widens: source: github lets a GitHub Action / Dependabot workflow drive the same triage → remediate → gate pipeline server-side.


What This Skill Does NOT Do

  • Does not perform SAST / secret scanning / container scanning — it is dependency vulnerability management. (Those are candidate siblings in a future security family.)
  • Does not design or implement breaking major upgrades — routes them to the engineer skill.
  • Does not rewrite application code — owns manifests and lockfiles only.
  • Does not commit or push — the caller (commit gate) owns that; standalone it hands back staged changes.
  • Does not publish to Confluence/Notion — any architect routing it triggers stays local unless asked.
  • Does not silently suppress findings — every exclusion is recorded with a reason.

References

  • references/source-local.md — Phase 1 local-audit adapter (default) + pre-commit hook.
  • references/source-github.md — Phase 2 GitHub Dependabot adapter (alerts + security-update PRs).
  • references/severity-policy.md — severity normalisation, gate thresholds, SAFE/BREAKING classification.
  • references/vuln-report-template.md — the report structure.
  • references/ecosystems/{javascript,python,rust,go,csharp}.md — per-ecosystem audit tool, fix command, lockfile regen, transitive-override mechanism.
  • scripts/scan_dependencies.py — cross-ecosystem runner (osv-scanner primary, native fallbacks).
  • skills/sprint-executor/SKILL.md · skills/task-executor/SKILL.md — the commit-step gate callers.
  • skills/clean-code-commit/SKILL.md — validates the fix(deps): … commit message.
  • skills/{javascript,python,rust,go,csharp}-data-engineer/SKILL.md — breaking-upgrade implementation targets.

Feedback

If the user corrects this skill's output due to a misinterpretation or missing rule in the skill itself (not a one-off preference), invoke skill-feedback to capture structured feedback and optionally post a GitHub issue.

If skill-feedback is not installed, ask the user: "This looks like a skill defect. Would you like to install the skill-feedback skill to report it?" If the user declines, continue without feedback capture.