To check reachability by hand, find the vulnerable function named in the advisory, search your code and your dependencies for calls to it, trace whether production code paths reach those calls with attacker-influenced input, and record the evidence. It works for a few alerts a week. It does not scale past that.
What reachable means
A dependency can be present in your build without the vulnerable code ever running. Reachability asks whether your application can actually execute the vulnerable code path. It is a way of ordering work, not a promise of safety. An unreachable finding can become reachable when someone changes the code, so record when you checked.
The five steps
- Read the advisory closely. Find the affected function, class, or feature and the conditions needed to trigger it. Some advisories name a specific option or input type.
- Find direct use. Search your own code for imports and calls of that function. If you find none, move to the next step before you decide.
- Check indirect use. The vulnerable function may be called by another library you do call. Look at the dependency tree to see which direct dependency pulls in the vulnerable package.
- Trace the input. If the function is called, does attacker controlled data reach it? A parser fed only trusted files is a different risk from one fed user uploads.
- Record and date it. Write what you searched, what you found, and when. Set a review date.
What to write down
| Field | Example |
|---|---|
| Advisory | Identifier and affected function |
| Search done | Terms and paths searched |
| Result | Not called, or called with trusted input only |
| Decision | Dismiss with date, or fix |
| Review date | Next dependency upgrade day |
Where hand checks go wrong
- Searching only your own code. Indirect calls through libraries are the usual miss.
- Dynamic calls. Reflection and plugin systems hide call sites from text search.
- Configuration. The vulnerable feature may be switched on in config, not code.
- Stale conclusions. The answer changes with the next release.
When to stop doing this manually
Hand checks cost time per alert. They make sense when the alert count is small or the finding is high stakes. Once you are doing them weekly for many alerts, automation pays back. FIRST describes EPSS as an estimate of exploitation probability that does not account for your environment, and CISA's Known Exploited Vulnerabilities catalog says nothing about your code either. Reachability is the piece that does, which is why it is worth automating.
Never use an unreachable result to dismiss something listed in CISA's catalog without a second look at deployment context, since CISA strongly recommends prioritizing those entries.
For a broader view, see is the vulnerable code reachable: triage a zero day.
Try it yourself
Click through it at your own pace, or open it full screen. Compare the call paths shown with the ones you would trace by hand.
Safeguard's reachability analysis automates this trace, and the free scan at gold.safeguard.sh/scan shows it on your own repository.
Quick check
Is a text search for the function name enough?
Not alone. It misses indirect calls, dynamic calls, and configuration. Treat it as a first pass.
Can an unreachable finding be ignored forever?
No. Set a review date, since code changes can make it reachable.
Sources
- FIRST, EPSS frequently asked questions
- CISA, Reducing the Significant Risk of Known Exploited Vulnerabilities
Last reviewed: 19 October 2026.