Vnaik.com

Package Managers and Security

October 2017


Installing packages with npm, pip and the like is such a routine part of software development that we rarely even pause to think about it, often installing packages as recommended by an answer on Stackoverflow without a second thought.

However, there is a growing trend of extensions and packages being taken over by hackers and advertising companies. [1] [2] [3] [4] [8][9]

This means installing packages can be dangerous and should be done with some amount of thought and planning.

Some dangers and considerations of package managers follow.


Typosquatting

Typosquatting refers to the practise of registering a package with a name similar to an existing package. People install this by mistake. This happened recently with npm when the crossenv package was typosquatted when someone create the package cross-env to serve malware in addition to the normal functionality of crossenv. [5] [6]

A carefully crafted malware package can go undected for a long time. In addition typos when installing packages. Eg. typing

npm install requist

where you meant to type

npm install request

can be dangerous if it installs a functionally equivalent package, but with malware bundled.

This excellent article on typosquatting package managers examines the issue in depth.


Version Pinning and auto updates

It is unsafe to use package managers without explicit version pinning. It is safest to install an exact version of a package, eg.

1.2.3
as opposed to
1.*.*
or even
1.2.*

even if your package manager allows the latter two.

There have been cases of package dev's accounts being taken over by hackers who then release a point version that auto upgrades itself.[7] Allowing packages to auto-update is not a good idea for security, but is also bad because you may wind up with entirely different packages across your dev and production environment or across developers. It is important to use npm-shrinkwrap or such to freeze package versions - and it is very important to maintain this carefully.

Remember that whether or not any update is major or minor is determined solely by the package publisher, so expecting minor versions to be safe in all cases is probably not realistic.


Obfuscated Code

Having obfuscated code in a package is a significant red flag. Obfuscated (or binary) code in a package is reason enough to do without the package. Remember that this is a dev package library not an end user app - and hidden/binary code absolutely does not belong in your dev tools. And even if the hidden code is currently not malicious, that may not be true later - hiding code makes it harder to scrutinise, something hackers are very likely to exploit to their advantage.


How packages become compromised

To sum up, packages can become compromised in various ways, including but not limited to:

And once a package is compromised a simple minor point release to inject malicious code combined with a package manager that auto-updates minor versions helps propagate the malware.


Dependency Hell

The OWASP lists using packages with known vulnerabilities in the top ten ways applications are vulnerable/become compromised.

As developers, we are ultimately responsible for our work - and if a third party package is compromised, through no fault of our own, it is still the developers who have to clean up and manage the situation as far as the code is concerned.

A barebones ExpressJs app created with the Express creation tool has about 50 dependencies (including sub-dependencies). That's a massive attack surface.

If a hacker detects a vulnerability in one package every single webapp on the Internet that uses the package is now compromised. This is a very strong incentive for hackers and you can expect the number of attacks on packages to rise over time. Visibility will be higher for more popular packages meaning you are likely to be notified of hacks sooner - if those hacks are ever detected in the first place.

To sum up,

Edit: Since this post was written npm has released an audit tool which can scan all packages in your package-lock.json and inform you of potential security issues.

Minimising package dependencies is still probably a very good idea.

In addition, as of 2019, Github can now scan certain projects (eg. Node and Python) for vulnerabilities on push to origin and advise on updating the packages. With Github's acquisition of Dependabot you can now have automatic pull requests created for out-of-date packages.