The Developer's Guide to Using NPM Audit to Create a Dependency Tree
Published November 21, 2023.
An Anchore survey found that 62% of companies were impacted by at least one supply chain attack in 2022. These attacks include SolarWinds, MIMECAST, HAFNIUM, and, most recently, the Log4j vulnerability. Such attacks have prompted companies to place security at the forefront of their priorities to protect their applications. According to Security Intelligence, approximately 54% of organizations consider supply chain security a top focus.
Over the years, package managers have introduced tools to tackle security vulnerabilities when packaging and bundling software packages. An example of such a tool is the NPM audit, used in the Node.js ecosystem.
This post will teach you how to use NPM audit to detect security vulnerabilities, view dependency trees, and fix detected vulnerabilities.
Overview of NPM audit
NPM audit is a built-in tool within the Node Package Manager (NPM) that scans your project for security vulnerabilities and provides assessment reports of known vulnerabilities and advice on possible fixes.
It involves cross-checking and reporting the current version of the installed packages in your project with reported vulnerabilities on the public NPM registry. The identified vulnerabilities can be classified into the following levels:
- Low: can be addressed at your discretion
- Moderate: can be addressed as time allows
- High: should be addressed as quickly as possible
- Critical: should be addressed immediately
Benefits of NPM audit
NPM audit is a great tool, as it is natively integrated and well-maintained in the Node.js ecosystem, providing an added layer of security for your applications. It enables you to leverage the community of open source contributors that constantly find and address security vulnerabilities as opposed to doing the tedious work yourself.
Furthermore, it serves as an advisory on published fixes and how to fix them. Because the identified vulnerabilities are separated into different levels, you can prioritize security fixes depending on their severity. This makes it possible to tap into NPM security expertise for developers in the ecosystem, with tooling built natively for their Node.js stack.
New NPM security update
Over the years, the maintainers of NPM have periodically seen incidents on the registry where NPM accounts are compromised by malicious actors who access popular packages and insert malicious code into them.
This led the maintainers and community to put in place some new measures to ensure the integrity of the registry. These security updates were launched with the NPM version v8 15.0, which was released on the 22nd of July 2022, and are present in all later versions.
- Resigned Packages: a new audit signature – the Elliptic Curve Digital Signature (ECDS) Algorithm, is available on the Command Line Interface (CLI). The signature allows you to verify your packages locally by running the npm audit signatures command.
- Redefined Login and Publishing Experience: the security of accounts has been significantly improved with the introduction of the Two-Factor Authentication (2FA) mechanism to prevent malicious actors.
- Social Verification: developers can now link their GitHub and Twitter accounts to their packages. This allows NPM to significantly improve the account recovery experience as the identity of the account owners can be verified across platforms.
NPM and your dependency tree
Before exploring NPM audit further, it is paramount to understand what a dependency tree is and how it relates to NPM audits when scanning dependencies to identify vulnerabilities in the entire supply chain.
Dependencies are libraries, packages, or pieces of software that are essential for a code to function. When a dependency is installed, it gets its own set of packages required to perform and work efficiently, creating a dependency tree.
The visual below shows examples of dependency trees:
package_A with its own dependencies
package_B with its own dependencies
How to use NPM audit to find and fix vulnerabilities
To get started with fixing and finding vulnerabilities in a project, you need to ensure that the project has package.json and package-lock.json files inside the repository. These files are required because NPM uses them to fetch required dependencies in a project.
Next, you need to upgrade NPM to the latest version and take advantage of all the recently released fixes. You can do this by running the command below:
npm install npm@latest –g
Once you have the latest version of NPM installed and the newest list of CVEs, you can then get started with scanning for vulnerabilities. To find vulnerabilities in a project, you can run the command below in your terminal:
The command submits the dependencies used in your project to the NPM registry and asks for reports of known vulnerabilities. It also categorizes the vulnerabilities in order of their severity.
NPM audit also supports viewing the vulnerability report in a JSON format. You can do that by running the command below:
npm audit –json
View dependency tree
NPM audit is actually quite flexible and enables you to view your findings in a few formats––aside from the tree and JSON listed above, you can also view your package-specific dependencies when auditing and reviewing your project vulnerabilities. You can do that by running the command below:
npm list <package name>
A sample of TypeScript dependencies in a React project is shown below:
npm list typescript
All of this is great, but eventually, this is just a first step when it comes to securing your Node.js applications. Once you are armed with this information, you can then go about actually securing your applications (based on the severity of the findings and their priority).
To get started with fixing vulnerabilities in a project, you can run the command below in your terminal:
npm audit fix
NPM audit also supports fixing vulnerabilities by doing any of the following:
- Passing the -force flag- some packages might require moving to a major version and therefore requires you to add the -force flag:
npm audit fix -force
- Upgrading to the latest version- NPM also lets you upgrade an existing package to the latest version with security fixes and patches:
npm install firstname.lastname@example.org
Avoiding breaking changes
At the moment, users cannot filter NPM fixes based on vulnerabilities. As much as upgrading packages to the latest version helps fix vulnerabilities, it must be done cautiously to avoid breaking changes. NPM-Check is a tool developed by the community to help upgrade packages by providing an interactive and intuitive UI to check for outdated, incorrect, and unused packages. In addition, NPM-Check separates dependencies from devDependencies and provides current versions with links to read changelogs and potential breaking changes.
To get started with NPM-Check, first, you need to install it by running the command below in your terminal:
npm install -g npm-check
Then, you can check and update vulnerabilities by running:
npm npm-check -u
Beyond manually running the NPM audit
Even with the continuous upgrades, security fixes, published versions, and patches that NPM keeps releasing, finding and fixing vulnerabilities is rigid and time-consuming. Therefore, developers need the proper security toolings they can leverage to find and fix vulnerabilities efficiently. Jit orchestrates security for Node.js stacks, so your developers can easily access and start working with npm-audit to scan their code dependencies for vulnerabilities.