Check three things: who declares the dependency, whether any code imports it, and whether anything loads it by name at runtime. If the answer to all three is nobody, remove it, run the tests, and rescan. Removal is the cheapest vulnerability fix because it leaves nothing to patch.
Step 1: who requires it
Every ecosystem has a command that answers why a package is present. Use the one for yours.
| Ecosystem | Command | What it shows |
|---|---|---|
| npm | npm explain with the package name | The chain of dependencies causing it to be installed |
| Go | go mod why with the module path | Why the module is needed |
| Cargo | cargo tree with the invert option | Packages that depend on the crate |
| Composer | composer depends with the package name | Which packages require it |
The npm documentation describes explain as printing the chain of dependencies causing a given package to be installed in the current project. The Cargo documentation describes the invert option as showing reverse dependencies. Composer describes depends as telling you which other packages depend on a certain package, and notes that dev requirements count only for the root package.
If another package requires it, you cannot simply delete it. You are in the transitive case, and removal means removing or replacing the parent.
Step 2: does your code import it
If the answer to step 1 shows only your own manifest, search the source for imports. Search across all languages in the repository, tests, scripts and build files, not only the main source folder. A dependency used only in tests is a dev dependency, not an unused one.
Watch for indirect use:
- Plugins or loaders that read module names from configuration files.
- Build tools that call a package by name from a script.
- Dynamic imports built from strings.
- Frameworks that auto discover packages by convention.
- Command line tools the package provides, called in CI.
Step 3: remove it on a branch and run everything
Remove the declaration, regenerate the lock file, and run the build, the tests and a smoke test. A failure in a rarely used path is possible, so check the code path list from step 2.
npm uninstall oldpackage
go mod tidy
composer remove vendor/oldpackage
The Go reference notes that go mod tidy and related commands operate on the main module. For a Rust crate, remove the line from Cargo.toml and rebuild. Compare the lock file before and after. Only the removed package and anything that was used solely by it should disappear.
Step 4: confirm the finding is gone
Rescan the built artifact. If the vulnerable package still appears, something else brings it in. Go back to step 1 for that path. See also the related guide on removing unused dependencies before you triage them.
When you cannot prove it
If you cannot show a package is unused, do not delete on hope. Options: keep it and mitigate, wrap it with a narrow adapter, replace it, or run in a staging environment with extra logging for a defined period. Also consider reachability. A package that is present but whose vulnerable function is never called is a different risk than one in constant use, though it is still worth removing on a schedule.
Try it yourself
Click through it at your own pace, or open it full screen. See how findings in code that is never called are separated from the ones that matter first.
Where Safeguard fits
Safeguard scans dependencies, runs reachability analysis to show which findings your code can actually reach, and can open fix pull requests through autonomous remediation. That last feature is off by default and every category starts on Manual, so a person approves each change. You can try a free scan on a repository first.
Quick check
Is a dev dependency unused?
No. If tests or build steps use it, it is needed in development even if it does not ship.
The package is still flagged after I removed it. Why?
Another dependency probably requires it. Run the why command again to find the new path.
Sources
- npm explain documentation
- cargo tree, The Cargo Book
- Composer command line reference, depends
- Go modules reference
Last reviewed: 19 October 2026.