Cve triage
47 Claude skills for security tradecraft across AppSec, Pentest, Blue Team, and GRC. NL/EU regulatory-anchored. Pattern-level discipline.
npx -y skills add roodlicht/accans-sec-skills --skill cve-triageAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Triage dependency vulnerabilities against CISA KEV, EPSS, reachability and compensating controls — turn a raw Dependabot/Snyk/osv-scanner dump into fix-now/sprint/quarter/accept decisions with rationale.
SKILL.md
12.8 KB, as published. Nobody here has run it
CVE Triage
When to use
This skill begins where the scan ends. It receives a list of CVE hits and decides per item: what's this worth, when do we fix, or do we not? Running the scan and building the SBOM happen elsewhere; this is the filter that separates noise from signal.
Triggers:
- An inbox of Dependabot/Snyk/Mend/osv-scanner/grype/Trivy findings to walk through.
- A new public vulnerability (Log4Shell-style, XZ-style, regreSSHion-style) with the question "does this hit us?".
- A CI dependency scan fails on a merge and someone has to decide: block or pass with rationale.
- Periodic (quarterly or release-gate) review of the open CVE portfolio, including reopening "accept-risk" decisions whose expiry is up.
- A
security-reviewphase-3 handoff for dep-vulns.
When NOT to use (handoff)
- Run a scan or build an SBOM →
supply-chain(SBOM, SLSA, provenance) andsast-orchestrator(SCA-tool configuration). - Code-level dep hygiene (pinning, dedupe, lockfile discipline) →
secure-codingphase 6. - Active exploitation or PoC construction →
web-exploit-triageorpayload-crafter. - Container/image vulns where the base image is the source →
container-hardeningfor the image part, then back here for per-CVE triage. - Secrets in dependencies →
secrets-scanner. - IR when an exploited vuln is in production →
ir-runbook. Triage is then too late; response comes first.
Approach
Six phases. Phase 3 is the heart: a decision tree you walk per CVE. The phases before and after are lighter.
1. Intake and normalization
- Consolidate sources. Dependabot/GHAS, Snyk, osv-scanner, grype, Trivy, Mend, GitLab dep-scanning. The same CVE from multiple tools = one item. Multiple CVEs in the same package = group per package, decide per CVE.
- Per entry record: package name, installed version, CVE-ID, ecosystem (npm/pypi/maven/...), introducer (direct or transitive via
X), fixed-in-version (when available). - Early filter (don't remove, label).
devDependenciesthat don't ship in the production bundle, optional features that are off, test fixtures. Label "not-in-prod"; they get an abbreviated phase-3 treatment. - Expiry check. Existing "accept-risk" decisions whose expiry is up or that have a new public exploit go back into the triage queue.
2. Context per service
Three questions that skew the whole judgement if you miss them. Answer them once per service; they apply to every CVE in that service.
- Exposure. Internet-facing unauthenticated, internet-facing authenticated, internal-only, or not-in-prod? An RCE in a service behind a VPN plus mTLS is a different story than the same RCE on a public endpoint.
- Data classification. PII, financial data, credentials of other services, production customer data, or just telemetry? Leakage impact depends on this.
- Deployment and compensating controls. Container with cap-drop and read-only FS? Serverless with limited runtime? WAF in front? Network segmentation? Least-privilege runtime user? Inventory upfront — these controls weigh in at phase 3e.
3. Per-CVE decision tree
Walk the steps in order. One step may be enough to land on "fix-now" (KEV + reachable + exposed); more often you walk all six.
(a) CISA KEV check. Is the CVE on the CISA Known Exploited Vulnerabilities Catalog? That means demonstrable active exploitation in the wild.
curl -s https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json \
| jq '.vulnerabilities[] | select(.cveID == "CVE-YYYY-NNNNN")'
A KEV hit defaults to fix-now, unless you have a strongly substantiated VEX-not-affected claim (see phase 4).
(b) EPSS score. FIRST's Exploit Prediction Scoring System: a probability (0–1) of exploitation in the next 30 days, refreshed daily based on observed exploit activity and vuln features.
curl -s "https://api.first.org/data/v1/epss?cve=CVE-YYYY-NNNNN" \
| jq '.data[0] | {cve, epss, percentile, date}'
Use as a relative signal within your portfolio, not a hard cutoff. The distribution is heavily skewed (the majority sits below 0.01). A percentile ≥ 95 means "this is in the top 5% of all CVEs by predicted exploitation"; that's the practical heuristic.
(c) Reachability. Is the vulnerable function actually called from your code, or is it in a code path you don't execute?
- Go:
govulncheck ./.... Official, call-graph-based, reports per CVE whether you reach the path. The gold standard per ecosystem when it comes to open-source tooling. - JavaScript/TypeScript, Python, Java: open-source call-graph tooling is less mature. Commercial: Snyk Reachable, Semgrep Pro, Endor Labs, Socket. Open-source heuristic: grep the vulnerable function name in your codebase plus the import chain.
- Unknown or not provable: treat as reachable. The burden of proof is on down-classification, not up-classification.
(d) Exposure modifier. Combine with phase 2.
- Internet-facing + pre-auth path → up.
- Internet-facing + auth-gated + auth-gated exploit → neutral to slightly up.
- Internal-only, within limited IAM scope → down.
- Not-in-prod (dev/test/staging) → down, but log it. If it ever moves to prod, the triage changes.
(e) Compensating controls. What's already in place.
- WAF rule that blocks the exploit pattern → modest reduction. WAF bypasses are rarely impossible; treat as temporary cover, not the solution.
- Sandbox, seccomp, cap-drop, minimal runtime user → modest.
- Input validation that makes the vulnerable input impossible → strong, but only if proven (no "we strip HTML so XSS can't happen").
- Network segmentation that shields the service → strong.
Document every claim. No verified control, no reduction.
(f) Impact estimate. From the CVE description and CVSS vector, not gut feel.
- Pre-auth RCE, auth bypass → high.
- Auth RCE → high.
- Info-disclosure with PII/credentials → high.
- Privilege escalation in-process → medium-high.
- DoS with service impact → medium.
- Crash without data impact → low-medium.
4. Decision
Four outcomes, each with a rationale you write down.
- fix-now (days to at most a week). Triggers: KEV hit, or reachable pre-auth RCE on an internet-exposed service. On long patch lead-time: implement a compensating control in parallel (WAF rule, feature flag) for cover during the fix window.
- fix-sprint (2–4 weeks). Reachable high-impact without active exploitation, or KEV with strong compensating controls. Plan within normal sprint cadence.
- fix-quarter (~3 months). Reachable medium, or high but not reachable or fully compensated. Handle as part of the next package upgrade cycle.
- accept-risk + VEX with expiry. Not reachable, low impact, or fully mitigated by controls. Always with a re-evaluation date — six months default, shorter if the situation is volatile. Write a VEX entry so the next scan cycle doesn't surface this again.
No decision without rationale. If "fix-quarter vs fix-sprint" can't be justified in one sentence: revisit.
5. Action
Patch path per case:
- Direct dep: bump to the fixed-in version, read the changelog for breaking changes, regression-test in staging.
- Transitive dep, direct parent not patched: try in order — npm/yarn
overridesorresolutions, pnpmoverrides, Poetry dependency override, Goreplacedirective ingo.mod, MavendependencyManagement, Gradleconstraints. Verify withnpm ls <pkg>orpip showormvn dependency:treethat the actually installed version is the fixed one. - No patch available: feature-flag the vulnerable path off, add targeted input filtering as an explicit mitigation with documentation, or fork-and-patch if the library is strategic. All three are temporary; log them with expiry.
- Replace library: last resort with unmaintained or structurally unsafe deps (e.g. XZ-style supply-chain compromise).
Rollout discipline:
- Staging first with at least one full regression cycle. Some security patches introduce behaviour changes that only show up at edge cases.
- Production deploy with elevated monitoring: error rates, latency, unexpected log errors.
- For transitive fixes: verify the actually installed version in production, not just the lockfile declaration.
Post-deploy monitoring: the package stays on your radar. New disclosure on the same package = arrange notification. "Accept-risk" entries with expiry get a calendar trigger so they don't quietly expire.
6. Verification-loop
Layer 1: scope (every open CVE assessed, no duplicates, no services skipped?), assumptions ("not reachable" backed by tool output or explicit code inspection, not gut feel?), gaps (tests and dev environments patched on fix-now?), adversarial reader (which decision would an auditor find weakest?).
Layer 2: CVE-IDs are real (NVD check), CVSS scores from NVD or vendor advisory and never self-derived, EPSS numbers with a date (scores change daily), KEV check against the live feed and not a week-old cache, VEX rationale references primary sources and not a blog.
Output
Per CVE a triage entry in this shape:
CVE-YYYY-NNNNN — <package>@<version>
Ecosystem: <npm | pypi | maven | go | cargo | ...>
Introducer: <direct | transitive via X → Y → Z>
CVSS v3.1: <score> (<vector>)
KEV: <yes | no>
EPSS: <0.xxxx — percentile — date>
Reachable: <yes | no | unknown — method>
Exposure: <internet-pre-auth | internet-auth | internal | not-in-prod>
Impact: <RCE | info-disclosure | DoS | ...>
Compensating: <list, or "none">
Decision: <fix-now | fix-sprint | fix-quarter | accept-risk>
Rationale: <1–3 sentences, why this decision given the signals above>
Action: <concrete patch path: "bump lodash to 4.17.21", "override transitive via resolutions", "feature-flag path X">
Expiry: <date — only on accept-risk or temporary mitigation>
VEX status: <affected | not_affected (+ reason) | fixed | under_investigation>
Summary at the top:
Triage — <scope / service>
Total: N CVEs over M packages
fix-now: n1 (<short list>)
fix-sprint: n2
fix-quarter: n3
accept-risk: n4
KEV hits: k | Reachable high/critical: r | Not-in-prod: p
Verification-loop:
Verdict: <pass | revise | rewrite>
Security verdict: <no red flags | red flag — ...>
Provide VEX entries (for not_affected and under_investigation) as OpenVEX JSON — a separate file scanners can consume so the next cycle doesn't re-surface 200 of the same CVEs. Each entry has at minimum: product identifier (pURL), CVE-ID, status, rationale (justification vocabulary from OpenVEX, e.g. component_not_present, vulnerable_code_not_in_execute_path).
A report without a rationale field per decision is not a triage report; it's a list with colours. Refuse to deliver.
References
- CISA KEV Catalog — https://www.cisa.gov/known-exploited-vulnerabilities-catalog. Public feed of actively exploited CVEs. JSON feed on the same domain under
/sites/default/files/feeds/. - FIRST EPSS — https://www.first.org/epss/. Model and API, daily score update.
- FIRST CVSS v3.1 — https://www.first.org/cvss/v3-1/specification-document. Base/Temporal/Environmental metrics. Note: NVD typically publishes only Base.
- FIRST CVSS v4.0 — https://www.first.org/cvss/v4-0/specification-document. 2023 publication. Some vendors already report in v4; portfolios may be mixed.
- CISA SSVC — https://www.cisa.gov/stakeholder-specific-vulnerability-categorization-ssvc. Formal decision tree. This skill is a simplified variant aimed at dev teams.
- OSV Database — https://osv.dev/. Ecosystem-aware vuln DB; underlying osv-scanner.
- OpenVEX spec — https://github.com/openvex/spec. Most minimalist machine-readable VEX format.
- CycloneDX VEX — https://cyclonedx.org/capabilities/vex/. Richer VEX integrated with CycloneDX SBOM.
- CSAF 2.0 — https://docs.oasis-open.org/csaf/csaf/v2.0/csaf-v2.0.html. OASIS standard, more vendor-oriented.
- govulncheck — https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck. Call-graph-based reachability for Go.
- osv-scanner — https://github.com/google/osv-scanner. CLI on OSV; reads lockfiles and SBOMs.
Categories
- core
- appsec