| name | vuln |
| description | Security vulnerability fix workflow. Researches CVEs via NVD, applies dependency and code fixes one at a time, runs Opus code review, and verifies with tests. Activated when the user prompt starts with "vuln:".
|
| allowed-tools | view, edit, create, bash, glob, grep, task, web_fetch, ask_user |
Fix security vulnerabilities: the argument (text following the vuln: trigger)
Each argument token is either JIRA-ID:CVE-ID (e.g. MGD-2423:CVE-2023-46604) or a bare CVE-ID (e.g. CVE-2023-46604). Parse and filter each token, research all CVEs first, then fix them one at a time.
Step 0 — Classify & Route (mandatory)
Load and follow the model-routing policy at ~/.copilot/installed-plugins/ihudak-copilot-plugins/dev-workflows/skills/_shared/model-routing.md, then classify per CVE, based on the size of the required repository change — not the CVE category alone.
Default heuristics:
| Required fix (from research output) | Classification |
|---|
| Patch or same-major minor bump, no source-code changes expected | MODERATE |
| Major version bump, or code changes required to adopt the new version | SIGNIFICANT |
| Major bump of a security-critical library, or code changes in auth/session/token/permission/payment/audit paths | HIGH-RISK |
Because the required fix is not known up front, start with a provisional MODERATE routing block for research, then finalize the classification from the research report before fix application begins.
Step 1 — Prepare
- Parse — Extract Jira ID (optional) and CVE ID from each token.
- Determine NOJIRA placeholder — Scan recent branch names and commit history for
NOJIRA / NO-JIRA; use the project convention when a Jira ID is missing.
- Filter — Skip non-CVE IDs (
CWE-*, OWASP patterns) with a warning.
- Snapshot repo context — Note the repo path and, when obvious, the primary ecosystem so the research agent can disambiguate detection.
Step 2 — Research (parallel)
Invoke one research task per valid CVE. Use a single agent message for the batch.
task(
agent_type: "dev-workflows:vuln-research",
model: `<detection_model — §2.1 detection chain>`,
description: "Research CVE",
prompt: "## Vuln Research Request
repo: [absolute repo path]
cves:
- id: [CVE-ID]
jira: [optional Jira key]
ecosystem_hint: [optional]
model_routing:
classification: MODERATE
reason: <one-line>
current_model: <the model this orchestrator is running under>
detection_model: <§2.1 detection chain: claude-sonnet-4.6, fallback claude-sonnet-4.5/gpt-5.4> # vuln-research; vuln-fixer (SIMPLE/MODERATE); review-fixer
planning_model: <§2 Opus chain> # vuln-fixer escalates here only if HIGH-RISK
review_model: <§2 Opus chain> # code-review (frontmatter-pinned; recorded, no override)
opus_available: <true if a §2 Opus model resolved, else false>
gate_tests_on_review: false
notes: <any §2 / §2.1 fallback or degradation>"
)
Collect all reports:
READY → candidate for fixing
NOT_IN_REPO → notify and skip
LOOKUP_FAILED → warn and offer retry or skip
SKIP_NON_CVE → already filtered; no further action
Finalize the per-CVE classification from the research output. If the finalized class is HIGH-RISK, re-run vuln-research on Opus for a confirmation pass. If it is SIGNIFICANT, re-run on Opus when the major bump or breaking-change surface is non-trivial.
Step 3 — Fix (sequential)
Process READY CVEs one at a time to avoid conflicting edits to the same dependency files.
SIMPLE / MODERATE path
Invoke vuln-fixer with baseline_tests: run-fresh:
task(
agent_type: "dev-workflows:vuln-fixer",
model: `<detection_model — §2.1 detection chain>`,
description: "Fix CVE",
prompt: "## Vuln Fix Request
repo: [absolute repo path]
phase: full
baseline_tests: run-fresh
jira_placeholder: [NOJIRA or omit]
model_routing:
classification: [MODERATE]
reason: <one-line>
current_model: <the model this orchestrator is running under>
detection_model: <§2.1 detection chain: claude-sonnet-4.6, fallback claude-sonnet-4.5/gpt-5.4> # vuln-research; vuln-fixer (SIMPLE/MODERATE); review-fixer
planning_model: <§2 Opus chain> # vuln-fixer escalates here only if HIGH-RISK
review_model: <§2 Opus chain> # code-review (frontmatter-pinned; recorded, no override)
opus_available: <true if a §2 Opus model resolved, else false>
gate_tests_on_review: false
notes: <any §2 / §2.1 fallback or degradation>
[paste the single READY research report verbatim]"
)
If the fixer returns status: TEST_REGRESSION, follow "Handling Test Failures" below, then
re-invoke vuln-fixer with phase: regression-resume + the chosen regression_decision,
passing the same CVE input verbatim.
SIGNIFICANT / HIGH-RISK path
- Capture baseline at the orchestrator using the existing
test-baseliner agent. Keep the full baseline block (passing_count and passing_tests).
- Invoke
vuln-fixer with review gating enabled:
task(
agent_type: "dev-workflows:vuln-fixer",
model: `<detection_model for SIGNIFICANT; planning_model (§2 Opus chain) only if HIGH-RISK>`,
description: "Apply CVE fix before review",
prompt: "## Vuln Fix Request
repo: [absolute repo path]
phase: full
baseline_tests: provided
baseline_passing: [captured count]
baseline:
passing_tests:
- [captured test ids]
jira_placeholder: [NOJIRA or omit]
model_routing:
classification: [SIGNIFICANT | HIGH-RISK]
reason: <one-line>
current_model: <the model this orchestrator is running under>
detection_model: <§2.1 detection chain: claude-sonnet-4.6, fallback claude-sonnet-4.5/gpt-5.4> # vuln-research; vuln-fixer (SIMPLE/MODERATE); review-fixer
planning_model: <§2 Opus chain> # vuln-fixer escalates here only if HIGH-RISK
review_model: <§2 Opus chain> # code-review (frontmatter-pinned; recorded, no override)
opus_available: <true if a §2 Opus model resolved, else false>
gate_tests_on_review: true
notes: <any §2 / §2.1 fallback or degradation>
[paste the single READY research report verbatim]"
)
-
If the fixer returns AWAITING_REVIEW, run Opus code review before tests:
- Capture the diff with
git add -N . && git diff
- Invoke
code-review with the CVE summary, the research handoff, the fixer output, and the diff (frontmatter-pinned to Opus; recorded as review_model above, no model: override needed)
- If review returns
BLOCK or PASS WITH RECOMMENDATIONS, invoke review-fixer with model: <detection_model — §2.1 detection chain> for BLOCKER and MAJOR findings, then re-run the Opus review once
- If the second verdict is still
BLOCK, stop and escalate; do not continue to tests, commit, or PR
-
Resume the fixer after review — Re-invoke vuln-fixer with phase: verify-resume, the same baseline block, and the original research report re-supplied verbatim.
-
If the fixer returns status: TEST_REGRESSION (from step 4's resumed verify), follow
"Handling Test Failures" below, then re-invoke vuln-fixer with phase: regression-resume +
the chosen regression_decision, the same baseline block, and the original research report
re-supplied verbatim.
Step 4 — Summarise
After all CVEs are processed, print a result table:
| CVE | Library | Change | Class | Result | PR |
|----------------|-----------------|----------------|--------------|---------|-----|
| CVE-2023-46604 | activemq-broker | 5.15.5→5.15.16 | MODERATE | OK | #42 |
| CVE-2024-99999 | (not in repo) | — | — | SKIP | — |
Append a ### Model Routing section summarising the per-CVE classification, why it was chosen, the models used, and any Opus review verdicts.
Then invoke impl-maintenance with a compact session handoff covering the CVEs fixed, notable regressions, workarounds, and overall outcome. Always pass Command run: vuln: in that handoff — omitting it makes impl-maintenance default to implement:, mislabeling the run.
Context hygiene. This was a large run — consider /compact to free context before your next task (per ~/.copilot/installed-plugins/ihudak-copilot-plugins/dev-workflows/skills/_shared/session-hygiene.md §3 — non-pipeline, so /compact only; guidance only).
Then persist plugin feedback (automatic). After impl-maintenance returns, project its plugin-facing slice into the specs repo by citing ~/.copilot/installed-plugins/ihudak-copilot-plugins/dev-workflows/skills/_shared/feedback-emission.md and calling its emit-auto entry point (§6). Pass the Lessons Learned report, command: vuln:, the run's jira_key (or null) and source, and plugin_version (read from ~/.copilot/installed-plugins/ihudak-copilot-plugins/dev-workflows/.plugin/plugin.json). emit-auto renders only the report's Command workflow improvements, New agents / skills, and plugin Reference docs sections plus the Key observations that triggered them (§4 plugin-facing predicate) — never target-project copilot-instructions.md/hook advice — as origin: auto entries, dedupes by stable id (§3), resolves the target via the §2 specs-first ladder, and writes silently. List the persisted path (or "no plugin-facing signal — nothing persisted") after the lessons-learned report. ADDITIVE — the impl-maintenance report still appears in the output; this step NEVER fails the run, NEVER commits, and NEVER writes into the code repo or the current working directory.
Handling Test Failures
vuln-fixer cannot prompt the user directly — sub-agents dispatched via the task tool run
in a separate context and have no access to interactive tools, even when one is listed in their
tools:. When it returns status: TEST_REGRESSION (previously-green tests now failing, not
auto-fixable), the orchestrator (this skill, running in the interactive session) handles the
decision:
Git Workflow
Branch naming
Inspect recent git history and existing branches to match the project's naming convention.
- With Jira ID:
fix/JIRA-ID-CVE-XXXX-XXXXX
- Without Jira ID:
fix/NOJIRA-CVE-XXXX-XXXXX (or fix/CVE-XXXX-XXXXX if the project omits placeholders)
Commit message
Use the project's existing style. Default template:
With Jira ID:
fix(deps): upgrade <library> to <version> to remediate <CVE-ID>
Resolves <JIRA-ID>
Fixes <CVE-ID> - <one-line CVE description>
Vulnerable range: <range>
Safe version: <version>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Without Jira ID:
fix(deps): upgrade <library> to <version> to remediate <CVE-ID>
Fixes <CVE-ID> - <one-line CVE description>
Vulnerable range: <range>
Safe version: <version>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
PR
- Base branch:
main (fallback: master)
- Title:
fix(deps): <library> upgrade to remediate <CVE-ID> (append [<JIRA-ID>] when present)
- Body: CVE summary, vulnerable range, version change made, classification, and test results (pass count before vs. after)
Invariants (always enforced)
- ALWAYS
emit-block (per ~/.copilot/installed-plugins/ihudak-copilot-plugins/dev-workflows/skills/_shared/feedback-emission.md) before escalating a halt caused by a plugin / skill / command / reference gap (a capability the run needed but the plugin lacked) — so a run abandoned at the block still records it. NEVER for a work-quality review BLOCK or an environment / user halt (repo-missing, dirty-tree, jira-not-found, cancellation)
- ALWAYS classify per CVE after research
- NEVER use Opus for a
MODERATE fix unless the user explicitly asks for it
- NEVER run tests for a
SIGNIFICANT / HIGH-RISK CVE before the Opus review returns a non-BLOCK verdict
- ALWAYS pass the captured baseline block back to
vuln-fixer on phase: verify-resume
- NEVER push directly to
main / master
- After the run, suggest
/compact (a big non-pipeline run) per ~/.copilot/installed-plugins/ihudak-copilot-plugins/dev-workflows/skills/_shared/session-hygiene.md §3 — compact-only, no clear/resume pointer; guidance only, never auto-run.