How to audit node.js modules

How to audit Node.js modules

Node.js is one of the best and most widely used Javascript runtimes used for building APIs. But, this popularity status has led to many hackers distributing insecure modules that exploit the Node.js application or provide a weak point for exploitation. In this tutorial, you will learn how to audit Node.js modules and also detect vulnerabilities in modules using npm audit.

Last year, GitHub found many vulnerabilities in the tar and @npmcli/arborist packages. The main vulnerability found in the tar package was caused by the insufficient protection of symlink whereas the main vulnerability found in the @npmcli/arborist package was caused by improper handling of symbolic links. These vulnerabilities could be exploited to overwrite files and execute arbitrary code.

These vulnerabilities can be exploited by hackers to execute code without your permission. With this ability, hackers could cause chaos and steal information. These vulnerabilities were a wake-up call for many Node.js developers to start updating and securing their modules and the Node.js environment.

Nodejs has provided a few mechanisms such as npm audit, which inspects modules and packages for vulnerabilities. It is essential to learn and familiarize yourself with these mechanisms in order to secure your Node.js applications.

Article Overview

  1. Security vulnerabilities affecting Node.js module
  2. How to scan and identify vulnerabilities
    1. Analyzing the npm audit printout text
    2. Classifying vulnerabilities found in Node.js modules and applications
  3. How to eliminate vulnerabilities in modules

Before you start reading this tutorial, make sure you have installed npm and Node.js.

Security vulnerabilities affecting Node.js modules

Node.Js modules are functions and programs that are meant to be reused in different packages and accessed by other Node.js programs. Modules eliminate the need to create functions that do the same purpose again and again.

Here are three types of modules:

  • Core modules
  • Local modules
  • Third-party modules installed using npm

Modules are the best medium used to share functions and objects with other developers and improve their workflow. Modules are widely used as they improve efficiency and help you learn new concepts when you are a beginner. You don’t have to start from scratch.

Good quality modules prevent vulnerabilities. Using trusted and secure modules will help you develop a secure Node.js application. But insecure modules are a great concern. Before using third-party modules, audit their security status and use only secure modules.

How to scan and identify vulnerabilities

The npm audit command is used to scan and detect security vulnerabilities in Node.js modules. After scanning your Node.js package it will give you an assessment report if there are vulnerabilities discovered in your packages. 

For example, if you were to install the latest version of express which is secure using the install command:

npm install express --save

You would get the following information which tells you how many packages were installed and audited. npm will automatically audit every package you install.

Since the latest express package is secure there are no vulnerabilities found:

added 50 packages, and audited 53 packages in 14s

3 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

But, if you install an insecure package or an old package version that has vulnerabilities you will get different results as the npm audit has discovered vulnerabilities.

Version 4.14.0 of express has many vulnerabilities:

npm install [email protected]

This express version has 8 vulnerabilities which are categorized into three categories:

added 2 packages, removed 8 packages, changed 20 packages, and audited 47 packages in 8s

1 package is looking for funding
  run `npm fund` for details

8 vulnerabilities (2 low, 2 moderate, 4 high)

To address all issues, run:
  npm audit fix --force

Run `npm audit` for details.

To get a clear and detailed report of the vulnerabilities discovered, run the following command:

npm audit

The npm audit command will give you the following detailed report, you will learn the report analysis in the next section of this tutorial. Here are the details for the first vulnerability detected by npm audit:

debug  <2.6.9
Regular Expression Denial of Service in debug - https://github.com/advisories/GHSA-gxpj-cx7g-858c
fix available via `npm audit fix`
node_modules/debug
  express  3.0.0-alpha1 - 4.15.5 || 5.0.0-alpha.1 - 5.0.0-alpha.6
  Depends on vulnerable versions of debug
  Depends on vulnerable versions of finalhandler
  Depends on vulnerable versions of fresh
  Depends on vulnerable versions of qs
  Depends on vulnerable versions of send
  Depends on vulnerable versions of serve-static
  node_modules/express
  finalhandler  <=1.0.5
  Depends on vulnerable versions of debug
  node_modules/finalhandler
  send  <=0.15.6
  Depends on vulnerable versions of debug
  Depends on vulnerable versions of fresh
  Depends on vulnerable versions of mime
  node_modules/send
  node_modules/serve-static/node_modules/send
    serve-static  <=1.12.6
    Depends on vulnerable versions of send
    node_modules/serve-static

Here are the details for the second vulnerability detected by npm audit:

fresh  <0.5.2
Severity: high
Regular Expression Denial of Service in fresh - https://github.com/advisories/GHSA-9qj9-36jm-prpv
fix available via `npm audit fix`
node_modules/fresh
  express  3.0.0-alpha1 - 4.15.5 || 5.0.0-alpha.1 - 5.0.0-alpha.6
  Depends on vulnerable versions of debug
  Depends on vulnerable versions of finalhandler
  Depends on vulnerable versions of fresh
  Depends on vulnerable versions of qs
  Depends on vulnerable versions of send
  Depends on vulnerable versions of serve-static
  node_modules/express
  send  <=0.15.6
  Depends on vulnerable versions of debug
  Depends on vulnerable versions of fresh
  Depends on vulnerable versions of mime
  node_modules/send
  node_modules/serve-static/node_modules/send
    serve-static  <=1.12.6
    Depends on vulnerable versions of send
    node_modules/serve-static

Here are the details for the third vulnerability detected by npm audit:

mime  <1.4.1
Severity: moderate
Regular Expression Denial of Service in mime - https://github.com/advisories/GHSA-wrvr-8mpx-r7pp
fix available via `npm audit fix`
node_modules/mime
  send  <=0.15.6
  Depends on vulnerable versions of debug
  Depends on vulnerable versions of fresh
  Depends on vulnerable versions of mime
  node_modules/send
  node_modules/serve-static/node_modules/send
    express  3.0.0-alpha1 - 4.15.5 || 5.0.0-alpha.1 - 5.0.0-alpha.6
    Depends on vulnerable versions of debug
    Depends on vulnerable versions of finalhandler
    Depends on vulnerable versions of fresh
    Depends on vulnerable versions of qs
    Depends on vulnerable versions of send
    Depends on vulnerable versions of serve-static
    node_modules/express
    serve-static  <=1.12.6
    Depends on vulnerable versions of send
    node_modules/serve-static

Here are the details for the fourth vulnerability detected by npm audit:

qs  6.2.0 - 6.2.2
Severity: high
Prototype Pollution Protection Bypass in qs - https://github.com/advisories/GHSA-gqgv-6jq5-jjj9
fix available via `npm audit fix`
node_modules/qs
  express  3.0.0-alpha1 - 4.15.5 || 5.0.0-alpha.1 - 5.0.0-alpha.6
  Depends on vulnerable versions of debug
  Depends on vulnerable versions of finalhandler
  Depends on vulnerable versions of fresh
  Depends on vulnerable versions of qs
  Depends on vulnerable versions of send
  Depends on vulnerable versions of serve-static
  node_modules/express

The audit report has shown two vulnerabilities recurring in different packages all of these vulnerabilities are classified as high. Here are the vulnerabilities:

  • Regular Expression Denial of Service(ReDoS)- This vulnerability occurs when cyber attackers exploit regex vulnerabilities in order to send many requests to your server more than it could handle. In this case, the server focuses on responding to the massive requests sent by the hacker. This attack causes the server performance to slow down and resources to become inaccessible to your users.
  • Prototype Pollution Protection Bypass- This vulnerability occurs when a hacker injects your applications with malicious code or input in order to change an object’s properties.

Analyzing the npm audit printout text

The audit report comprises the following details shown in the following table.

DetailExplanation
NameName of the module or package affected.
Level of the vulnerabilityThe report will state whether the vulnerability is critical, moderate, or low.
Name of the vulnerabilityThe report will show the name of the vulnerability.
LinkThis link will redirect you to a webpage that has more information about the vulnerability.
The main vulnerable packageThe report will give you the main affected module.
A list of vulnerable packages affectedThe report will also give you the list of the affected modules.
How to fix itThe report will suggest whether you should use npm audit fix or npm fix audit --force.

Classifying vulnerabilities found in Node.js modules and applications

After auditing Node.js modules the audit report will classify vulnerabilities into the following categories of severity:

  • Critical – vulnerabilities that should be addressed immediately
  • High – vulnerabilities that should be fixed as soon as possible
  • Moderate – vulnerabilities that should be fixed as time allows
  • Low – vulnerabilities that can be addressed at your own discretion

If a vulnerability is detected in an internet-facing application, there are high chances that hackers could exploit it. These vulnerabilities pose a serious threat. While vulnerabilities found in your local environment face fewer chances of exploitation when compared to vulnerabilities found in your internet-facing application.

How to eliminate vulnerabilities in modules

To fix the vulnerabilities detected in the previous section, run the following command to eliminate vulnerabilities:

npm audit fix

Npm audit has fixed the issues by changing and removing packages that had vulnerabilities:

added 8 packages, removed 2 packages, changed 20 packages, and audited 53 packages in 6s

3 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

Not all vulnerabilities will be solved by npm audit fix. Some will have to be eliminated by the --force flag. For example, install  optimist@^0.6.1 a package that has serious vulnerabilities:

Npm install optimist@^0.6.1

You will get the following output which shows major vulnerabilities being detected:

added 3 packages, and audited 4 packages in 2s

2 vulnerabilities (1 moderate, 1 high)

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.

This time if you run npm audit fix the vulnerabilities will not be solved:

up to date, audited 4 packages in 3s

# npm audit report

minimist  =0.6.0
  Depends on vulnerable versions of minimist
  node_modules/optimist

2 vulnerabilities (1 moderate, 1 high)

To address all issues (including breaking changes), run:
  npm audit fix --force

The npm audit fix --force is used whenever vulnerabilities that have been detected affect the root project and cannot be updated without changing the dependency ranges. Since the vulnerabilities detected in the optimist@^0.6.1 package cannot be eliminated completely using npm audit fix, the --force flag has to be used to completely eliminate vulnerabilities:

npm audit fix --force

You will get an output that shows that all critical and minor vulnerabilities have been solved:

npm WARN using --force Recommended protections disabled.
npm WARN audit Updating optimist to 0.5.2,which is a SemVer major change.

removed 1 package, changed 1 package, and audited 3 packages in 4s

found 0 vulnerabilities

Conclusion

Since most of the modules used are official third-party modules, it is easy to believe that they have no vulnerabilities since they are created by developers who have more knowledge and experience than many developers. But, as long there is code, bugs and vulnerabilities will always exist. Auditing and testing your applications is the only way you can spot vulnerabilities in order to eliminate them.

Therefore, consistently auditing your modules is the key to developing and delivering secure Node.js applications. Knowing if your modules have no vulnerabilities should be the first information you should inquire about before starting the application development procedure.

This blog post was created as part of the Mattermost Community Writing Program and is published under the CC BY-NC-SA 4.0 license. To learn more about the Mattermost Community Writing Program, check this out.

Read more about:

node.js npm security

Boemo is a software developer who embraces innovative approaches and likes diving deep into complex topics. Boemo enjoys writing about DevOps and has been published on a number of websites including Dzone, LogRocket, Vultr, Boemo has a degree in Computer Science from the University of Botswana.