The NodeSource Blog

A High Level Post Mortem of the eslint-scope Security Incident

Early today there was an incident regarding a module (eslint-scope) that was hijacked on npm. The hijacked module attempted to steal tokens contained within .npmrc to enable additional publishes . Here's a quick overview of everything that's happened, based on the information available so far.

*This post will be updated as more information becomes available. Feel free to ping me on Twitter with additional information, I’d be happy to make updates corrections as necessary. *

This has been totally from my point of view while observing and reaching out to individuals who I know it matters to. I figured I’d take a minute to summarize the entire event and give a quick post-mortem for y’all in case you don’t have as much time to investigate and work on this stuff as I do.

Module Highjacking

The hijacker of eslint-scope published a new patch release of the module at 10:40 UTC. Normally, a new patch would automatically hit many of the individuals using the module (either directly or as a dependency of another module).

Today at 11:17 UTC, an issue was created in the GitHub repository of eslint-scope regarding unexpected error messages which indicated that the downloaded module was malicious as of v3.7.2. The GitHub issue elicited rapid responses and quickly became ground-zero for the incident, as other users were able to reproduce and confirm the unexpected errors.

Passwords for npm accounts were not vulnerable to this attack.

The hijacked version of the module would load a file from pastebin and attempt to send users’ .npmrc files back to the hijacker. Since .npmrc contains authentication tokens for users' accounts, it’s reasonable to suspect that the hijacker’s code was intended to behave as a worm – gaining publish access to other accounts that don't have publish-time 2FA enabled on npm.

The origin of these new and unexpected errors was traced back to some moderately sloppy code, which some have suggested indicates the attacker didn’t have a firm understanding of certain aspects of basic best practices in both JavaScript and Node.js.

Another module, eslint-config-eslint, was also infected but the attacker actually reverted it and went for the bigger fish – eslint-scope, which has roughly 1000 times the weekly downloads. Both babel-eslint and webpack depend on the hijacked module eslint-scope.

At this point, the ESLint team has published a post-mortem of their discoveries.

npm Team's Response

The npm team began investigating the issue early in the morning PT (16:13 UTC), which was a few hours after the initial incident began to garner attention.

In investigating, the npm team came to the conclusion that account credentials had been compromised and the malicious code was published by the compromised account, which had publish access to the module.

Not too long after, the npm team invalidated all tokens created prior to the publication of the hijacked module – which rendered any credentials received by the module’s hijacker useless. This action helped to ensure that additional modules would not be compromised by the same hijacker using valid credentials stolen in the initial attack. The npm team also began reaching out to notify affected individuals.

As a result of the token deletion, npm inadvertently took down the npmjs.com website for a short amount of time – it was brought back up within a relatively short time frame with zero additional issues.

At 18:52 UTC, the npm team confirmed on their Status Page that they had indeed invalidated all tokens and would be conducting further forensic analysis to understand how many modules and users were affected by the malicious code.

The npm team has also published a post-mortem in which they state that ~4500 accounts could have been affected by stolen tokens prior to the hijacked eslint-scope module being unpublished, but as yet no evidence has been found that any of these accounts were affected prior to the full token purge.

The npm team did a good job handling the incident in a way that – while unfortunate – ensures that any stolen credentials are now effectively useless.

Current State of Things – the TL;DR

If you're still a bit uneasy, here are a few things you can do immediately to help ensure that you're not going to be affected further:

  • Check internal registries to ensure that the eslint-scope@3.7.2 and eslint-config-eslint@5.0.2 modules aren't cached
  • Make sure both package-lock.json and npm-shrinkwrap.json files don't include eslint-scope@3.7.2 and eslint-config-eslint@5.0.2
  • Run npm cache clean to ensure that your cache is flushed of the offending modules

If you’ve got an npm account and publish, it’s highly encouraged that you enable 2FA for your npm accounts. I personally have enabled it for both sign-in and publishing, and I suggest you do the same – especially if you maintain modules that others depend on

N|Solid is a superior Node.js platform enhanced to help you build, manage, secure, and analyze mission-critical Node.js applications.

Get Started

Build, manage, secure, and analyze mission-critical Node.js applications with a superior Node.js runtime.

Get Started

Monitor local module usage for security vulnerabilities, license issues, and more.

Get Started