npm client leaked authentication tokens

As recently announced the npm client supports installing packages from locations that are outside of the official npm registry (such as at HTTP urls). Due to a design flaw introduced in late 2014 the authentication bearer tokens used to authenticate the npm client with the registry were being sent along with all requests, not just to the official registry.

So, if you or one of the modules you use specified a dependency like the below example, your authentication token would be leaked to that location. Note this is not your password but a token representing that credential.

{
  "dependencies": {
    "fantastic-dependency": "http://example.com/fantastic-dependency.tgz"
  }
}

If that endpoint specified was HTTP and not HTTPS, that token was not transmitted securely and should be considered compromised.

During the time of the flaw there were 163 modules out of 250k+ modules that specified a remote package url that was not github.com or npm registry, these urls appear to be limited to 71 unique domains.

github.com itself would get tokens leaked to it for just over 5k modules. These modules may not today have a github.com reference, but did so for at least 1 publish during their life span.

So there is possibly a good chance that your token was leaked. But there are some very simple things you can do to take action.

How to protect yourself

First make sure you are running the updated and patched npm clients. The flaw has been fixed in npm@2.15.1 and npm@3.8.3

Run npm --version to see what version you are using

$ npm --version
3.8.1

The next thing you should do is go revoke your old tokens.

You do this by visiting https://www.npmjs.com/settings/tokens

Note that if you have tokens in use by continuous integration or deployment systems they will have to be reconfigured as well. While it's a hassle, it's well worth the effort to ensure that tokens are protected.

Finally, if you want to see if you leaked a token to a url that's not https://registry.npmjs.org here is a one liner that Node Security team member Nathan LaFreniere came up with. It will output "true" if any of the modules’ sources came from something other than registry.npmjs.org, and will list false if they all came from an official source.

Note it depends on jq being installed.

npm ls --json | jq '[recurse(.dependencies | .[]?) | .resolved? | try test("^https://registry.npmjs.org")] | all | not'

The below command will give you the entire list so that you might audit each of the endpoints yourself.

npm ls --json | jq 'recurse(.dependencies | .[]?) | .resolved?'`

Additional reading http://blog.npmjs.org/post/142036323955/fixing-a-bearer-token-vulnerability http://nodejs.org/en/blog/vulnerability/npm-tokens-leak-march-2016/

You might also enjoy reading: