Over the last few years, the popularity of Node.js has been steadily increasing. Huge companies like Twitter, eBay, Netflix, Reddit, and Paypal use it to power their backends and handle their increasing traffic. And startups aren’t trailing behind either, as they are adopting this Javascript runtime to build their websites and leverage its advantages.
Given that growing interest in Node.js, at BairesDev we believe that this is the right time to share some of the best practices around it, especially those concerning security. The following are 8 great practices to follow when working with this framework, regardless if you work as a freelancer, with an in-house team, or as a part of a Node.js development company.
#1 Protect From Query Injections With Parameterized Queries
SQL/NoSQL injections are one of the most common attacks a website can suffer nowadays. Malicious agents send queries as if they were user inputs and force the system to provide them with sensitive information mistakenly. This is typically what happens when you use JS strings or string concatenations to insert values in queries.
Fortunately, you can avoid that by using one of the many Node.js libraries with built-in capabilities against these injections. Mongoose is one of the best ones at that, as it provides you with support for indexed parameterized queries. By doing that, you’ll treat all inputs as such, preventing any information from being mistaken for an executable SQL statement.
#2 Pay Attention to HTTP Headers
Let’s face it – HTTP headers can be both beneficial and harmful. Using the wrong ones or even employing the right ones in the wrong places can lead to cross-site scripting and clickjacking, among other known attacks. What can you do? You can’t get rid of the HTTP headers, so you can do one of 2 things: either pay attention to each one and assess them manually or secure them with Helmet.
Helmet is a relatively small but rather powerful Node module that can help you improve your header security just by installing it. Of course, you can easily configure it to further its capabilities but, overall, you don’t have to do that much to get its help in adding or removing headers.
#3 Don’t Run Node.js With A Root User
This may feel like pretty basic stuff, but you’d be surprised about how many developers don’t pay attention to this. Running Node.js code with root access opens the door for any malicious actor to attack you when you aren’t expecting it. Using a root user is indeed easier for specific tasks (like changing a directory the user isn’t allowed to write), but you should try some workarounds to prevent that from happening.
Yes, I understand if you see this as an exaggeration, but it’s worth highlighting that each time you run code with sudo, you are exposing yourself to attacks. Even when that seems like a worst-case scenario, be sure always to run the code with non-root users.
#4 Be Careful With Eval
Or don’t use it at all, if possible. Sure, eval can make your code more dynamic but it can also allow attackers to input malicious code that your application will end up running. Since eval executes any string of characters as code, you can never be sure as to what kind of input the eval statement will deal with. Naturally, this can lead to all types of security issues, such as DoS attacks.
Those attacks are at the extreme of what you can suffer via eval. You might use it and not have any problems at all. You can use it securely if you are careful enough, but that’s the problem – you have to pay attention to many details to avoid the vast array of issues that may come.
#5 Use 2FA To Deter Automated Attacks
A broken authentication system is one of the biggest vulnerabilities you can have. If you implement weak password and session management policies in your applications, you expose yourself to attackers stealing credentials and implanting malicious code on your websites. That’s why you have to consider the multiple aspects that come with authentication: password creation and recovery, ID management, etc.
You can always use existing solutions like OAuth to deal with all that, but there’s another thing you should use: two-factor authentication (2FA). You can integrate it into your application or website through npm or Yarn packages and generate one-time tokens for all users.
#6 Accept Only Small-Sized Payloads
Any Node.js application can receive large requests that can put its performance under threat. That’s because the more significant the payload, the more processing power it will take, which will divert that power from other, more critical tasks. Since a single thread executes the payload, an attacker can take your system without sending many requests – just a few with a bigger body payload.
Fortunately, that’s a program you can solve fairly quickly through the use of Express’ body-parser, a middleware that will parse the incoming request bodies before your handlers. Thus, you can limit the body size of all incoming requests and accept those that have body size under an accepted predefined threshold.
#7 Keep All Environments With Different Credentials And Access Levels
One of the biggest vulnerabilities you can have is leaving your web applications in the hands of weak security rules. That often happens when you leave default user account passwords, package settings, and access levels across the different environments. Both development and staging environments are often more loosely secured, so if their configurations and passwords remain the same in production, you expose yourself to misconfiguration and brute force attacks.
The solution to this is to tweak the default settings to ensure that each environment has distinct credentials and access levels. Thus, you ensure that no known vulnerabilities make it to production.
#8 Monitor Dependencies
One of the most common things to happen when you work with Node.js is that you end up having many dependencies on just one project. Thus, if you don’t keep them in check, you can have multiple vulnerabilities and entry points for attackers to exploit. The solution? To keep a tight track record of all the dependencies in your projects.
This will allow you to know which dependencies you’re using at all times and provide you with the possibility of knowing which ones you need to path. The best way to do so is by using tools like Snyk and npm audits, which can go a long way, mainly if you use them in the context of a continuous improvement approach.
Stepping Up Your Node.js Game
These practices are just the tip of the iceberg. There are plenty more things you can do to step up your security game in Node.js. Fortunately, there are plenty of guides and tools you can follow to ensure you have the highest protection level you can get out of it. I know doing so can be daunting at times, but it’s the safest way to enjoy all of Node’s benefits without compromising your web apps’ integrity, aligning well with the responsibilities outlined in a NodeJS job description.
If that feels like a challenging effort, don’t sacrifice the security of your Node applications. Simply hire a development company with enough expertise to tackle your projects – a company like BairesDev! We follow these and other security practices when working with Node.js in our web application projects, and we can help you leverage its power and give you a robust final product.