Node Modules are a great tool that vastly reduces app development time and cost. However, third-party Node Modules can also cause major security issues and other threats. Let's take a closer look at the dangers of using Node Modules and figure out how to keep our apps safe.
Executing someone else's code
The biggest problem with third-party npm packages is that we run someone else's code on our computers, servers and clients. Do we trust them? Should we trust them? There are multiple reasons we shouldn't, for example:
- They may have put malicious code intentionally
- They may have accidentally created unsecure code
- They may have missed something and accepted a bad merge request
We could review their code to ensure it's safe. However, we are not guaranteed to find all vulnerabilities. Furthermore, a thorough code review takes a lot of time - significantly more than executing "npm install ...". It might be faster not to use third-party packages and write our own solutions.
If we still want to use a package and we don't want to review it's code, we can use these methods to mitigate the risk:
- Prefer packages owned by well-known trustworthy orgnisations or people
- Check "first publish date" on npmjs.com - avoid new packages
- Check "weekly downloads" - a steady large number of downloads is a good sign
- Check issues on GitHub - we don't want packages with unresolved security issues
Nested packages
Packages often use other packages, which use other packages and so on. Therefore we have to trust authors of all these libs. It makes verification process much more time-consuming. A good idea is to prefer packages with a smaller tree of dependencies.
Updates
Sometimes we need to update a package to fix an issue or get a new functionality. It's worth noting that updates introduce new unverified code or new packages.
Bugs
If a third party library has a bug that breaks our app, we may be able to figure out a workaround (e.g. call the library in a different way). However, in many cases it's not possible. We can report the problem to the author and wait who-knows-how-long for a fix. We can also fork the repository and fix the bug ourselves, but it's not a perfect solution either. We are not familiar with their code, so it may take us a lot of time to figure out how to fix the problem and we may create new bugs.
Another problem is that packages may be incompatible with each other. For example they may write and read the same global variable. This kind of problems is often difficult to debug.
Performance
Third-party solutions aren't always created with top-tier performance in mind. Sometimes it's not a problem; sometimes it will significantly slow down our app. In some cases packages do more stuff than we need - for example we have to call generateReport()
function to generate a complete report, but all we need is one field.
Bundle size
Have you ever wondered why is the bundle so large? Often it's because of a large number of packages. In many cases reducing bundle size improves user experience and saves some money. That's why it's important to choose the correct package... or write our own lean solution.
Other problems
Licences
Before we install a package we have to ensure that it's licence permits us to use it in our project. If we don't do it, we risk getting ourselves and/or our companies into trouble. Some projects use non-standard, complicated licences - in these cases we may have to ask a lawyer or choose a different package. It's a good idea to add an automatic licence checker that will let us know that we have added a package with a non-whitelisted licence.
Dependance on the owner of the package
Some authors abandon their projects and they no longer provide bugfixes and new features. Occasionally they change the licence or require a payment for the "next-generation" of the package. In this case we can still use the old one, but we may not get any updates.
Summary
People often install packages without doing any verification, because executing "npm install ..." is a fast and convenient way of getting things done. However, this may lead to big problems. That's why I always recommend doing at least some basic checks. In many cases a third-party lib is not needed - the feature we want may not take a lot of time to implement. Sometimes, especially in large companies, it may be beneficial to spend some time on developing an internal library with common features.
Third party packages are very useful, but they clearly have a dark side - and we should be aware of it.