3 Ways to Improve the Security of Open-Source Node Dependencies
While open-source software can be extremely beneficial, some major risks come with using it. Many developers don’t know the extent of these risks, or even that they’re using open-source software at all! According to a report, the average Web application or API has 26.7 serious vulnerabilities. Most organizations often have tens of thousands of applications, which can potentially be fatal!
Thankfully, there are plenty of ways to increase your security while using open-source, and this article will explain how you can do just that.
Before we go into how to improve the security of your node.js dependencies, you must understand the severity of using compromised open-source software. Let’s look at the two biggest security breaches caused by open-source software.
The Equifax Breach
If you don’t know what Equifax is, it’s one of the credit reporting agencies that assesses the financial health of nearly everyone in the United States. This automatically means it has the personal information of over 95% of United state citizens including social security numbers, addresses, credit card numbers, birthdates, etc. In September 2017, Equifax released a statement that said hackers had stolen the sensitive information of 147 million people.
The real question is: how did the hackers do it? How did the hackers access the servers of the most important companies in the United States?
The answer is; by accident. The hackers were crawling the web for vulnerable servers, and they came across the dispute server of Equifax. They then used a known Apache Struts vulnerability to hack into three Equifax servers.
Here’s how the Struts vulnerability worked: If attackers sent HTTP requests with malicious code tucked into the content-type header, Struts could be tricked into executing that code, potentially opening up the system Struts was running on to further intrusion.
The hackers were able to spend up to 6 months in the Equifax servers before they were discovered and eventually booted out. By then, the harm was already done. Equifax was criticized for everything from insufficient security to a bungled reaction to the incident, and top officials were accused of wrongdoing in the aftermath.
The ESlint heist
In 2018, a vulnerability was found in a module called eslint-scope, which is a dependency of several popular JavaScript packages such as babel-eslint and webpack. The module was hijacked by a hacker in an attempt to steal tokens from .npmrc. The hacker released a new patch of the module with a trojan in it, and many developers that were using the library started using the new patch.
It was a brilliantly executed plan, but it fell apart because of some poorly written code. The hacker did not have a strong background in Javascript and Node.js best practices, and this made his hack easy to fix. The npm team invalidated tokens created before the publication of the hijacked module This rendered any credentials obtained by the hijacker of the module completely useless, hence ensuring the security of additional modules.
By now, you probably know, you already understand the risk of having low security in node.js dependencies. Now, let's talk about how to mitigate those risks. First, we'll be looking at several questions you can ask which can reduce your risk substantially.
What packages am I using?
Logically, the more packages you use, the higher the chances that you'll have a malicious package. This is true not only for the packages you directly use but also for any of the dependencies those packages may have.
Finding the dependencies you use is as simple as running npm 1s
in your application's parent folder to see which packages you're using. You can use the —prod
parameter to only see production dependencies (which have the most influence on your security), and —long
to receive a brief overview of each package.
You can also use Dependency Management Services like bitHound and VersionEye to list and track the dependencies you use. Once you know all your packages, the next question to ask is
Am I still using this package?
As we all grow and evolve, so does our code. Most developers tend to stop using some packages, but instead of removing them, they just add new ones. At the end of the day, most projects tend to have a lot of unused dependencies which may become a security risk.
The depcheck tool is the best way to check for unneeded dependencies. Depcheck searches your code for requires and import commands and correlates them with the packages installed or mentioned in your package .json
, and generate a report. The command can be customized in a variety of ways using command flags, making it simple to automate checking for unneeded dependencies.
Next, and perhaps the most important question
Are other developers using this package?
In this case, the more the merrier. If more people are using a particular package, the less likely it is to be hacked. And if it is eventually hacked, the chances of finding the hack fast are higher for a package that is widely used.
For instance, the eslint-scope incident. The problem was only discovered when an issue was submitted in the eslint-scope GitHub repo, pointing to an unexpected error message indicating that a specific version of the module was harmful. The GitHub issue drew immediate answers and quickly became the focal point of the incident, where all of the debate took place.
Finally, the last question you should ask yourself is
Does this package have any known vulnerabilities?
If a package has known vulnerabilities, it presents a future risk to your project or organization. Approximately 15% of packages contain a known vulnerability, either in their code or in the dependencies they bring in. According to Snyk's analysis, around 76% of Node developers employ vulnerable dependencies in their apps.
Snyk makes it simple to identify such insecure packages. You may run snyk
test in your terminal or use the web UI to quickly test your GitHub repositories for insecure dependencies. Other testing alternatives can be found on Snyk's test page.
Finally, let’s look at things you can do to improve the security of your packages.
Choose a good Repository Hosting Service
By definition, launching an open-source project means the code must be publicly available to everyone, so it has to be hosted on a publicly available platform that everyone has access to. A version control system must also be utilized so that multiple developers can work on the project at the same time. Git is the most used version control system among developers today, so using that is advised.
If for some reason you don’t want to use GitHub, you can use BitBucket, GitLab, and Launchpad. Note that while these are also free, they’re far less popular, meaning there’ll be fewer eyes on your code. They also offer lesser engagement and they offer less helpful tools than GitHub. Just putting it out there.
Keep your dependencies updated
Now, this might seem obvious, but you’d be surprised by the number of developers who use outdated packages. It’s not like they do it on purpose, they just…forget. That’s a serious security breach though because there are many security bugs that are constantly unearthed and in most cases, quickly patched. It is fairly uncommon to find newly reported vulnerabilities resolved just on the most recent branch/version of a given project.
Consider the Regular Expression Denial of Service (ReDoS) vulnerability discovered in the HMAC package 'hawk' in early 2016. This hawk bug was rapidly fixed, but only in the most recent major version, 4.x. Older versions, such as 3.x, were fixed much later, despite the fact that they were equally vulnerable. As a rule, you should always use the latest version.
The npm outdated
command is the quickest way to see if you're running the most recent version. This command supports the -prod
flag to ignore any dev dependencies and the —json
flag to simplify automation.
Inspect the packages you use on a regular basis to ensure they are up to current. You can accomplish this in two ways: through the npm UI or by executing npm view <package> time.modified.
Use security tools
There are a ton of tools that have been developed to tackle the problem of identifying security vulnerabilities in different source components. Each tool was designed to approach the matter in a different manner, but we’re going to look at three of the most popular security tools around today.
RetireJs: RetireJS is a JavaScript-specific dependency checker that is open source. The project is largely concerned with usability. As a result, it includes a command-line scanner as well as plugins for Grunt, Gulp, Chrome, Firefox, ZAP, and Burp. RetireJS also provides a site-checking tool for JS developers who wish to discover if they're utilizing a JavaScript library with known vulnerabilities.
Hakiri: Hakiri is a commercial application that uses static code analysis to provide dependency testing for Ruby and Rails-based GitHub projects. It provides free blueprints for open-source public projects and premium plans for private companies. It makes use of the NVD and the Ruby Advisory Database. But they’re also looking to include connections with Slack, JIRA, and Pivotal Tracker, as well as support for other platforms such as Node.js and PHP.
Dependency-check: Dependency-check is a well-maintained open-source command-line utility from OWASP. It can be used independently as well as in build tools. Dependency-check is compatible with Java,.NET, JavaScript, and Ruby. The tool obtains its vulnerability data solely from the NIST NVD.
Conclusion
Working with open-source software is fantastic for developers. It gives us access to thousands upon thousands of pieces of code that we can easily use in our own projects and even offer improvements back to. However, with great power comes great responsibility. There are a lot of pitfalls when it comes to using open source libraries and packages in your applications, but taking precautions will keep you and your users safe.