Scanning
Phantom Dependencies

Phantom Dependencies

A phantom dependency is a dependency that is used in the code but not properly declared in a manifest file.

For example, consider a scenario where you specify a dependency on axios (opens in a new tab) in your package.json.

{
  "dependencies": {
    "axios": "^1.7.2"
  }
}

The axios package internally depends on follow-redirects see axios' package.json (opens in a new tab). Even though follow-redirects is a dependency of axios and not explicitly declared in your package.json, it is still possible to load it in your code:

const followRedirects = require('follow-redirects');
console.log(followRedirects);

This is possible because the npm package manager downloads follow-redirects into the node_modules folder when axios is installed. The require function does not check the package.json file and will load the follow-redirects module as long as it is present in the node_modules folder.

Using phantom dependencies is generally considered an anti-pattern and can lead to bugs and unexpected behavior. For example, imagine axios is updated to a new version that no longer depends on follow-redirects. If you are using follow-redirects in your code, it will break when you update axios.

Most programming languages and package managers suffer from design issues that make it possible for phantom dependencies to be used in the code.

Phantom Dependencies and Reachability Analysis

Since phantom dependencies are quite common, reachability analyses should be designed to scan for vulnerable functions in them. Coana’s reachability analysis is designed to scan dependencies regardless of how they are declared. If a reachable vulnerability is detected in a phantom dependency, the UI labels it as such.

Vulnerabilities in phantom dependencies are neither more nor less severe than vulnerabilities in declared dependencies.