Test reachability by planting cases whose answer you already know: a vulnerable function that is called, one that is not, and one that is only called through reflection or a framework. A good tool gets the clear cases right and says "unknown" for the hard one instead of guessing.
What reachability is claiming
Reachability analysis asks whether your code can actually call the vulnerable part of a dependency. If it cannot, the finding is lower priority. If it can, the finding is urgent. The claim is attractive because it can remove a large share of alerts. It is also easy to overstate, because call graphs are hard in dynamic languages.
Build the test set
Pick a small repo and add dependencies with known advisories that name a specific function. Then create four situations:
- Direct call. Your code calls the vulnerable function. Expected: reachable.
- Imported, never called. The package is imported but the function is not used. Expected: unreachable.
- Transitive call. A package you use calls a vulnerable function in one of its dependencies. Expected: reachable through the chain.
- Dynamic call. The function is invoked through reflection, dependency injection or a string lookup. Expected: unknown or reachable, not unreachable.
Record the right answer for each before running any tool. Keep the key away from vendor staff.
Score what you see
For every tool, make a table of tool answer against expected answer.
- A false "unreachable" on a case that is reachable is the dangerous error. Weight it heavily.
- A false "reachable" costs time but is safe.
- "Unknown" on hard cases is acceptable and honest.
Ask also whether the tool shows the path it found. A call path you can read lets a developer verify the claim in minutes. A bare label forces trust.
Check the edges
- Does it work across the languages you ship, or only one?
- Does it handle your build setup, such as a monorepo or a generated code folder?
- How long does it add to a scan?
- What happens with a dependency that has no function level advisory data? The honest answer is that function level reachability cannot apply and the tool should say so.
- Does it keep suppressed findings visible for audit, with the reason?
Try it yourself
Click through it at your own pace, or open it full screen.
Watch how the finding list changes once reachability is applied, then ask yourself what evidence you would need to trust each removal.
Treat the reduction number carefully
A vendor may quote a percentage of alerts removed. That figure depends on the code base it was measured on. Your own pilot is the only number that counts. Count the findings before and after on the same repos, and spot check a sample of the removed ones by hand. For a method, see measuring false positives in a pilot.
Safeguard offers reachability analysis alongside dependency scanning, and you can try a free scan on your own project to see how the output reads.
Quick check
Is unreachable the same as safe?
No. It means the vulnerable code is not called today. A code change can make it reachable later, so keep monitoring.
How many planted cases are enough?
Ten to twenty across the four situations gives a useful signal without turning the pilot into a research project.
Last reviewed: 19 October 2026.