Staying ahead of security vulnerabilities with security patches

| By Liran Tal

Traditionally, as part of the software development workflow, teams typically release new versions of their packages or apps in order to fix security issues as they arise.

With open-source projects however, because maintainers are usually volunteers and may get distracted by their routine commitments, it may take time before fix releases for packages are published. This can create a significant gap between the time a vulnerability is discovered and the time at which it is fixed and is advertised publicly; and unfortunately, without an officially published version with a fix for that software component, the risk of exploitation increases.

To cope with such cases, Snyk curates security patches for open source JavaScript projects in the npm ecosystem. By doing so, we help maintainers keep their packages safe and stay ahead of the security curve even when they aren’t free themselves to fix security issues immediately. Snyk applies a security fix directly to any affected npm package, in coordination with the maintainer. In this way, even if there is no official release that addresses the issue (and also if the release may break your build), we’ve got you covered.

Why are security patches important?

The time gap until a security fix is released by open source maintainers can have serious impact. For this reason, security patches are essential. As a testament to this, we can refer to prototype pollution vulnerabilities, which were recently discovered in the popular JavaScript library lodash.

Snyk’s security research team discovered prototype pollution vulnerabilities in lodash (CVE-2019-10744) affecting all versions. From the time of discovery, we worked with John Dalton, the lodash maintainer, through a responsible disclosure process to communicate the findings and provide security fixes that address the vulnerabilities.

Once the fixes were public as a Pull Request to fix said security issue in the lodash repository, the clock began counting down to an official lodash release with these fixes.

The vulnerability information was made public on July 2nd 2019, but the official release lagged behind for a week and was only published on July 9th 2019.

The security patch provided by Snyk’s mechanism is free for all users. We proactively open Pull Requests to apply the patch and remediate the security vulnerability, and protect your projects.

How does Snyk apply security patches?

Snyk’s module patching mechanism works by integrating with the npm package.json script support for lifecycle events. The npm process enables remediation programs to seamlessly integrate with the npm lifecycle management during different phases of your build, such as when npm is installed, when it is published to a registry and so on.

The npm documentation page has extensive information about all available npm lifecycle events and how and when they work.

Snyk uses the prepublish lifecycle event in package.json to apply patches before the package is packed and published, and also whenever npm install is run locally and includes no additional arguments. To further see how this works we can create some packages locally and use verdaccio as a local npm registry to experiment with module publishing and installation.

With an npm init -y and an update to our experimentation module aaa to include a prepublish script, the code looks like this:


{
  "name": "aaa",
  "version": "1.1.0",
  "description": "",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "prepublish": "echo hello little green world"
  },
  "main": "index.js",
  "keywords": [],
  "author": "",
  "license": "ISC"
}

When we run an npm install on the command prompt the following is displayed:

Our npm lifecycle event was executed, by which this short text is printed to the console and by which Snyk applies necessary patches as well.

Snyk updates your prepublish event setup to appear as follows:


"scripts": {
  "snyk-protect": "snyk protect",
  "prepublish": "npm run snyk-protect"
}

When an npm install is run, Snyk finds out which vulnerabilities exist in your code, downloads a patch from our database to fix the vulnerability, and applies it on the vulnerable module in the node_modules folder.

This means that when you clone a project, install all dependencies for it and run it, Snyk is invoked during the module installation process to patch the security vulnerability.

For Node.js projects, when you execute the application, it’s already protected. For a typical JavaScript library that does code transpilation such as with a module bundler like webpack, babel or typescript, then the result of the bundle that often exists in dist/ also includes the patched security vulnerability.

How does npm prepublish work?

Perhaps you are following different flows and not just a simple npm install for your project, meaning you may be skipping the prepublish event. In such cases, Snyk patches aren’t applied.

To understand npm’sprepublish script event better, let’s review how it gets called:

  • npm install
  • npm install --dev
  • npm ci
  • yarn
  • yarn install
  • yarn install --frozen-lockfile

When doesn’t npm’s prepublish event get called?

  • npm install --prod
  • yarn install --prod

As I discussed earlier, when running npm install with additional arguments, prepublish is not included. Therefore, if your workflow for installing npm module dependencies includes runningnpm install --prod, then you can invoke Snyk’s snyk protect directly instead. 

For example, consider the following Travis CI configuration:


install:
  - npm install --prod
  - snyk protect

Snyk security patches for libraries

In our npm package experiments we used these two libraries:

  • aaa – which has security vulnerabilities in its dependencies, and for which its maintainers have not delivered any newer versions with an official fix. Snyk patches fix these instances.
  • bbb – uses aaa as its own dependency

So in our use case, aaa is used by the bbb project. When bbb installs its dependencies such as by running npm install, the prepublish lifecycle event for aaa does not run.

This means that unless aaa was published to the registry as a transpiled bundle including all of its dependencies, which is something that is only common for frontend libraries, then upon installing aaa in bbb, the aaa’s nested libraries still include the same known security vulnerabilities.

In such cases, the maintainer of the bbb parent library should remediate the security vulnerabilities by offering patches that would then also resolve the nested dependencies for aaa

Summary

In closing, when maintainers are unable to release new versions with security fixes quickly enough or in worse cases, maintainers are no longer involved in projects any longer and are completely unresponsive, the risk of security vulnerabilities existing for longer time periods further increases. For these reasons, surgical security patches are a crucial tool to help you stay ahead of un-remediated security vulnerabilities