Package Managers and Security
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.
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 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.  
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.3as opposed to
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. 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.
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:
- Typosquatting (eg. cross-env vs crossenv)
- Dev accounts getting phished
- Dev straight out sells the package (offers of $50k for popular packages are not uncommon)
- Attackers manage to inject code into the package without the dev catching on
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.
More secure than a house of cards
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,
- There is no foolproof way to be sure your packages are secure so being vigilant is important
- Do not allow any automatic package updates. Instead carefully plan and manage updates manually
- Maintaining a local package cache may help but is hard to maintain
- Package audit tools like Nsp or Bundler-audit can help; and if you use Github it can automaticall audit npm packages for you
- Tools such as Dependabot can help you maintain your project dependencies
- It is important to have a smooth deployment process - so security fixes and package updates can be applied quickly and with minimal effort wherever possible, and ideally this can be done out-of-band from regular deployment schedules.
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.