Vuln Research — CVE Deep-Dive and Applicability Assessment
When a CVE drops, the question isn't "do we have this package?" — dependency-audit answers that. The questions are:
- Is the vulnerable code path actually invoked in our usage?
- Is there a public proof-of-concept making this easy to exploit?
- Is there a patch? When? What's our exposure window if we can't deploy in 24 hours?
- If we can't patch, what's the mitigation?
- Is CISA tracking it as actively exploited?
This skill walks that workflow end-to-end. Pairs with dependency-audit (which surfaces the CVE in the first place) and finding-triage (which closes the disposition loop).
Workflow
Step 1 — Pull the canonical sources
Start with the authoritative descriptions; everything downstream is summarized or sometimes wrong.
- NVD record —
https://nvd.nist.gov/vuln/detail/CVE-YYYY-NNNNN
- Vendor advisory — search the vendor's security page; this is usually the most accurate description of which versions are affected and what the fix is
- GitHub Security Advisory —
https://github.com/advisories/GHSA-... (often more concise than NVD, sometimes has detail NVD lacks; check the parent project's security tab)
- CISA Known Exploited Vulnerabilities catalog —
https://www.cisa.gov/known-exploited-vulnerabilities-catalog. If the CVE is here, treat as actively exploited — patch within CISA's stated due date
- EPSS score —
https://www.first.org/epss/ — Exploit Prediction Scoring System; a 30-day probability of exploitation. Useful tiebreaker between high-CVSS-low-EPSS vs medium-CVSS-high-EPSS
Step 2 — Confirm affected versions
Vendor advisories sometimes hedge ("affects versions before X"); pin down the exact range.
- Check the vendor's release notes and the commit history of the fix
- For OSS projects: find the patch commit (usually mentioned in the advisory) and run
git tag --contains <commit> to see which releases include the fix
- For closed-source: the advisory is the only source — verify version comparisons carefully (semver isn't always observed)
- For monorepos / re-publishers: confirm the same fix landed in any forks or distributions you depend on
Step 3 — Map to your environment
# Is the package installed at all?
npm ls <package> # or yarn why <package>, pnpm why <package>
pip show <package> # or pip list | grep <package>
bundle info <gem>
go list -m all | grep <package>
# What version exactly?
# Inspect lockfiles directly — the resolved version is what runs, not the range
grep -A1 '"<package>"' package-lock.json
# Where is it used?
# Direct dependency, transitive, dev-only?
npm ls <package> --omit=dev # production-reachable?
If transitive, walk up the dependency tree until you find which direct dependency is pulling it in. That's where the override / pin / replacement lives.
Step 4 — Reachability analysis (the high-leverage step)
A CVE is only exploitable if you actually call the vulnerable code path. This is where dependency-audit's noise gets cut down to real risk.
Read the patch. The fix commit shows exactly which function / file / API was vulnerable. Then:
# Does your code call the vulnerable function directly?
grep -rn "vulnerableFunction\|VulnerableClass" . \
--include="*.{js,ts,py,rb,go,java}" \
--exclude-dir=node_modules
# Does the dependency call it internally even if you don't?
# Trickier — you have to read the parent's source. For an indirect call:
cd node_modules/<package>
grep -rn "vulnerableFunction" .
Common reachability outcomes:
- Reachable, direct: You call the bad code. Highest priority — patch or workaround now
- Reachable, indirect: Your dependency calls the bad code as part of normal use. Still high priority
- Not reachable: The bad code is in a feature you don't use (different module, different entry point, different runtime). Lower priority; still recommend patching but won't break SLA
- Unknown: Document as unknown and patch on the cautious side
Don't write "not reachable" without showing the work. Future-you will want to revisit when usage changes.
Step 5 — Check for public PoCs and active exploitation
- GitHub: search for
CVE-YYYY-NNNNN in code and repos — PoCs land here within days of disclosure
- CISA KEV: if listed, it's actively exploited in the wild
- Exploit-DB:
https://www.exploit-db.com/ — confirmed exploits
- Vendor's security mailing list: sometimes the most recent intel
- GreyNoise:
https://www.greynoise.io/ — internet-wide scanning telemetry; if attackers are mass-scanning for this, your exposure window is now
- Twitter / Mastodon security circles — for breaking intel, but verify against canonical sources before acting
EPSS interpretation:
| EPSS score |
Meaning |
| > 0.7 |
High probability of exploitation in next 30 days — treat as urgent |
| 0.1 – 0.7 |
Meaningful exploitation likelihood — patch on regular cadence |
| < 0.1 |
Low predicted exploitation — patch when convenient |
EPSS is empirically tuned; it correlates better with actual exploitation than CVSS does.
Step 6 — Patch / mitigate / accept-risk
Patch (preferred):
- If a patched version exists and you can deploy quickly — upgrade the package, run tests, deploy
- For transitive deps without a direct patch, use
overrides (npm) / resolutions (yarn) / pin to force the patched version
Mitigate (when you can't patch):
- Disable the affected feature if your code doesn't need it
- Add a request-level filter (WAF rule, proxy filter) that blocks the known-malicious input pattern — for exploitation that goes through HTTP, this is often deployable in hours
- Network-segment the vulnerable service so it can't be reached from untrusted networks
- Add detection (see
siem-detection) so you'll see exploitation attempts even if mitigations fail
Accept risk (only when truly justified):
- Code path is genuinely unreachable in your usage
- Vulnerable component is in an internal-only service with no untrusted input
- Compensating controls reduce exploitation likelihood / impact enough to justify
- See the Accepted Risk disposition in
owasp-audit's Report Format — three required fields (why, compensating controls, re-evaluation trigger). No exceptions.
Step 7 — Document and close the loop
After deciding:
- Record the decision in your vuln-tracking system (Jira, Linear, Vanta, etc.)
- For accept-risk: set a re-evaluation date and a calendar reminder
- For patches: confirm via
npm ls / lockfile that the patched version is actually deployed (rollouts are not the same as decisions)
- For mitigations: write a runbook entry so the next person knows the mitigation exists and why
Common research traps
- The advisory says "fixed in vX" but the package never released vX — happens with abandoned projects. Use
overrides to a known-good fork, or replace the dependency
- The vendor patched it silently — fix landed before the CVE; advisory is for the version before the silent fix. Verify the fix commit is in your version
- The CVE applies to a sibling package you also have — same code, different name (forks, monorepo siblings). Search every package you have for the vulnerable function, not just the named one
- The CVSS is high but the EPSS is low — usually means complex preconditions in the wild. Patch but don't panic
- The CVSS is medium but the EPSS is high — usually means it's already being exploited in mass scans. Treat as urgent
- The PoC needs auth that's hard to get — but your application makes that auth easy to get (signup is open). The "complexity" attacker rating doesn't account for your threat model
Output Format
# Vulnerability Assessment: CVE-YYYY-NNNNN
## Date: [date]
## Assessor: [name]
### Summary
- **Title:** [from advisory]
- **CVSS / EPSS:** [scores]
- **CISA KEV:** [yes / no, and due date if listed]
- **Affected versions:** [exact range]
- **Our version:** [version + how installed]
### Reachability
- **Direct call:** [yes / no — with evidence]
- **Indirect via dependency:** [yes / no — with evidence]
- **Verdict:** Reachable / Not reachable / Unknown
### Exploitation availability
- **Public PoC:** [yes / no — link]
- **Active exploitation:** [yes / no — source]
### Decision
- [ ] Patch (target deploy: [date])
- [ ] Mitigate (controls: [list]; re-evaluate: [date])
- [ ] Accept risk (why / compensating controls / re-eval trigger)
### Action items
| Item | Owner | Deadline |
|------|-------|----------|
### References
[Links to advisory, patch commit, PoC, EPSS, CISA, etc.]
Boundaries
- Research vulnerabilities affecting code, dependencies, or systems the user has authorization for
- Do not develop, weaponize, or distribute exploits — read existing PoCs only for the purpose of assessing applicability
- For internal-only vulnerabilities or pre-disclosure intel, do not redistribute without authorization
- If research surfaces an unreported vulnerability in someone else's code, follow responsible disclosure — do not publish, do not exploit
- Refuse requests to use CVE research output to attack systems
References
- NVD (National Vulnerability Database)
- CISA Known Exploited Vulnerabilities Catalog
- GitHub Security Advisories Database
- EPSS (Exploit Prediction Scoring System) — FIRST.org
- MITRE CVE —
cve.mitre.org (now redirects to cve.org)
- Exploit-DB
- GreyNoise — internet scanning telemetry
- "Patch Tuesday" / vendor-specific cadences for context on disclosure timing
- Project Zero disclosure policy — the reference for responsible disclosure timelines
1---
2name: vuln-research
3description: "Research a specific CVE or vulnerability disclosure end-to-end — what version is affected, is your code reachable, is there a public PoC, is there a patch, what's the exposure window, what's the mitigation if you can't patch immediately. Use when the user mentions 'CVE,' 'vulnerability research,' 'is this CVE relevant,' 'zero-day,' 'CISA KEV,' 'GitHub Security Advisory,' 'reachability analysis,' 'patch analysis,' 'exploit availability,' 'EPSS,' 'CVSS,' or 'should we drop everything and patch this.'"
4allowed-tools: Read, Grep, Glob, Bash, WebSearch, WebFetch
5---
6
7# Vuln Research — CVE Deep-Dive and Applicability Assessment
8
9When a CVE drops, the question isn't "do we have this package?" — `dependency-audit` answers that. The questions are:
10
11- Is the vulnerable code path actually invoked in our usage?
12- Is there a public proof-of-concept making this easy to exploit?
13- Is there a patch? When? What's our exposure window if we can't deploy in 24 hours?
14- If we can't patch, what's the mitigation?
15- Is CISA tracking it as actively exploited?
16
17This skill walks that workflow end-to-end. Pairs with `dependency-audit` (which surfaces the CVE in the first place) and `finding-triage` (which closes the disposition loop).
18
19## Workflow
20
21### Step 1 — Pull the canonical sources
22
23Start with the authoritative descriptions; everything downstream is summarized or sometimes wrong.
24
25- **NVD record** — `https://nvd.nist.gov/vuln/detail/CVE-YYYY-NNNNN`
26- **Vendor advisory** — search the vendor's security page; this is usually the most accurate description of which versions are affected and what the fix is
27- **GitHub Security Advisory** — `https://github.com/advisories/GHSA-...` (often more concise than NVD, sometimes has detail NVD lacks; check the parent project's security tab)
28- **CISA Known Exploited Vulnerabilities catalog** — `https://www.cisa.gov/known-exploited-vulnerabilities-catalog`. If the CVE is here, treat as actively exploited — patch within CISA's stated due date
29- **EPSS score** — `https://www.first.org/epss/` — Exploit Prediction Scoring System; a 30-day probability of exploitation. Useful tiebreaker between high-CVSS-low-EPSS vs medium-CVSS-high-EPSS
30
31### Step 2 — Confirm affected versions
32
33Vendor advisories sometimes hedge ("affects versions before X"); pin down the exact range.
34
35- Check the vendor's release notes and the commit history of the fix
36- For OSS projects: find the patch commit (usually mentioned in the advisory) and run `git tag --contains <commit>` to see which releases include the fix
37- For closed-source: the advisory is the only source — verify version comparisons carefully (semver isn't always observed)
38- For monorepos / re-publishers: confirm the same fix landed in any forks or distributions you depend on
39
40### Step 3 — Map to your environment
41
42```bash
43# Is the package installed at all?
44npm ls <package> # or yarn why <package>, pnpm why <package>
45pip show <package> # or pip list | grep <package>
46bundle info <gem>
47go list -m all | grep <package>
48
49# What version exactly?
50# Inspect lockfiles directly — the resolved version is what runs, not the range
51grep -A1 '"<package>"' package-lock.json
52
53# Where is it used?
54# Direct dependency, transitive, dev-only?
55npm ls <package> --omit=dev # production-reachable?
56```
57
58If transitive, walk up the dependency tree until you find which direct dependency is pulling it in. That's where the override / pin / replacement lives.
59
60### Step 4 — Reachability analysis (the high-leverage step)
61
62A CVE is only exploitable if you actually call the vulnerable code path. This is where dependency-audit's noise gets cut down to real risk.
63
64**Read the patch.** The fix commit shows exactly which function / file / API was vulnerable. Then:
65
66```bash
67# Does your code call the vulnerable function directly?
68grep -rn "vulnerableFunction\|VulnerableClass" . \
69 --include="*.{js,ts,py,rb,go,java}" \
70 --exclude-dir=node_modules
71
72# Does the dependency call it internally even if you don't?
73# Trickier — you have to read the parent's source. For an indirect call:
74cd node_modules/<package>
75grep -rn "vulnerableFunction" .
76```
77
78**Common reachability outcomes:**
79
80- **Reachable, direct:** You call the bad code. Highest priority — patch or workaround now
81- **Reachable, indirect:** Your dependency calls the bad code as part of normal use. Still high priority
82- **Not reachable:** The bad code is in a feature you don't use (different module, different entry point, different runtime). Lower priority; still recommend patching but won't break SLA
83- **Unknown:** Document as unknown and patch on the cautious side
84
85Don't write "not reachable" without showing the work. Future-you will want to revisit when usage changes.
86
87### Step 5 — Check for public PoCs and active exploitation
88
89- **GitHub:** search for `CVE-YYYY-NNNNN` in code and repos — PoCs land here within days of disclosure
90- **CISA KEV:** if listed, it's actively exploited in the wild
91- **Exploit-DB:** `https://www.exploit-db.com/` — confirmed exploits
92- **Vendor's security mailing list:** sometimes the most recent intel
93- **GreyNoise:** `https://www.greynoise.io/` — internet-wide scanning telemetry; if attackers are mass-scanning for this, your exposure window is now
94- **Twitter / Mastodon security circles** — for breaking intel, but verify against canonical sources before acting
95
96**EPSS interpretation:**
97
98| EPSS score | Meaning |
99|---|---|
100| > 0.7 | High probability of exploitation in next 30 days — treat as urgent |
101| 0.1 – 0.7 | Meaningful exploitation likelihood — patch on regular cadence |
102| < 0.1 | Low predicted exploitation — patch when convenient |
103
104EPSS is empirically tuned; it correlates better with actual exploitation than CVSS does.
105
106### Step 6 — Patch / mitigate / accept-risk
107
108**Patch (preferred):**
109- If a patched version exists and you can deploy quickly — upgrade the package, run tests, deploy
110- For transitive deps without a direct patch, use `overrides` (npm) / `resolutions` (yarn) / `pin` to force the patched version
111
112**Mitigate (when you can't patch):**
113- Disable the affected feature if your code doesn't need it
114- Add a request-level filter (WAF rule, proxy filter) that blocks the known-malicious input pattern — for exploitation that goes through HTTP, this is often deployable in hours
115- Network-segment the vulnerable service so it can't be reached from untrusted networks
116- Add detection (see `siem-detection`) so you'll see exploitation attempts even if mitigations fail
117
118**Accept risk (only when truly justified):**
119- Code path is genuinely unreachable in your usage
120- Vulnerable component is in an internal-only service with no untrusted input
121- Compensating controls reduce exploitation likelihood / impact enough to justify
122- See the Accepted Risk disposition in `owasp-audit`'s Report Format — three required fields (why, compensating controls, re-evaluation trigger). No exceptions.
123
124### Step 7 — Document and close the loop
125
126After deciding:
127
128- Record the decision in your vuln-tracking system (Jira, Linear, Vanta, etc.)
129- For accept-risk: set a re-evaluation date and a calendar reminder
130- For patches: confirm via `npm ls` / lockfile that the patched version is actually deployed (rollouts are not the same as decisions)
131- For mitigations: write a runbook entry so the next person knows the mitigation exists and why
132
133## Common research traps
134
135- **The advisory says "fixed in vX" but the package never released vX** — happens with abandoned projects. Use `overrides` to a known-good fork, or replace the dependency
136- **The vendor patched it silently** — fix landed before the CVE; advisory is for the version before the silent fix. Verify the fix commit is in your version
137- **The CVE applies to a sibling package you also have** — same code, different name (forks, monorepo siblings). Search every package you have for the vulnerable function, not just the named one
138- **The CVSS is high but the EPSS is low** — usually means complex preconditions in the wild. Patch but don't panic
139- **The CVSS is medium but the EPSS is high** — usually means it's already being exploited in mass scans. Treat as urgent
140- **The PoC needs auth that's hard to get** — but your application makes that auth easy to get (signup is open). The "complexity" attacker rating doesn't account for *your* threat model
141
142## Output Format
143
144```markdown
145# Vulnerability Assessment: CVE-YYYY-NNNNN
146## Date: [date]
147## Assessor: [name]
148
149### Summary
150- **Title:** [from advisory]
151- **CVSS / EPSS:** [scores]
152- **CISA KEV:** [yes / no, and due date if listed]
153- **Affected versions:** [exact range]
154- **Our version:** [version + how installed]
155
156### Reachability
157- **Direct call:** [yes / no — with evidence]
158- **Indirect via dependency:** [yes / no — with evidence]
159- **Verdict:** Reachable / Not reachable / Unknown
160
161### Exploitation availability
162- **Public PoC:** [yes / no — link]
163- **Active exploitation:** [yes / no — source]
164
165### Decision
166- [ ] Patch (target deploy: [date])
167- [ ] Mitigate (controls: [list]; re-evaluate: [date])
168- [ ] Accept risk (why / compensating controls / re-eval trigger)
169
170### Action items
171| Item | Owner | Deadline |
172|------|-------|----------|
173
174### References
175[Links to advisory, patch commit, PoC, EPSS, CISA, etc.]
176```
177
178## Boundaries
179
180- Research vulnerabilities affecting code, dependencies, or systems the user has authorization for
181- Do not develop, weaponize, or distribute exploits — read existing PoCs only for the purpose of assessing applicability
182- For internal-only vulnerabilities or pre-disclosure intel, do not redistribute without authorization
183- If research surfaces an unreported vulnerability in someone else's code, follow responsible disclosure — do not publish, do not exploit
184- Refuse requests to use CVE research output to attack systems
185
186## References
187
188- NVD (National Vulnerability Database)
189- CISA Known Exploited Vulnerabilities Catalog
190- GitHub Security Advisories Database
191- EPSS (Exploit Prediction Scoring System) — FIRST.org
192- MITRE CVE — `cve.mitre.org` (now redirects to `cve.org`)
193- Exploit-DB
194- GreyNoise — internet scanning telemetry
195- "Patch Tuesday" / vendor-specific cadences for context on disclosure timing
196- Project Zero disclosure policy — the reference for responsible disclosure timelines