Improve the security of your Node.js app with the Node.js Security Handbook made for developers.
Avoid using fs, child_process and vm modules with user data
The fs module allows access to the file system. Using it with unsafe data can allow a malicious user to tamper with the content of your server. The child_process module is used to create new processes. Using it can allow a malicious user to run their own commands on your server. The vm module provides APIs for compiling and running code within V8 Virtual Machine contexts. If not used with a sandbox, a malicious user could run arbitrary code within your web application.
Node.js fs module documentation: https://nodejs.org/api/fs.html
Node.js child_process module documentation: https://nodejs.org/api/child_process.html
Node.js vm module documentation: https://nodejs.org/api/vm.html
Don't implement your own crypto
The problem with cryptography is that you don’t know you are wrong until you are hacked. So don’t do your own crypto. Use standards instead. For most crypto related operations, the ‘crypto’ core module can help you.
When using a templating engine, do not use unsafe methods
When using a templating engine, you should know which syntax can introduce XSS vulnerabilities. For instance, Pug (formerly, Jade) escapes all inputs by default unless you use the ‘!’ symbol.
Check Pug’s documentation: https://pugjs.org/language/code.html
Mustache documentation: https://mustache.github.io/mustache.5.html
Enforce a secure code review checklist
Go hack yourself
Once in a while, the entire technical team should sit together and spend time targeting all parts of the application, looking for vulnerabilities. This is a great time to test for account isolation, token unicity, unauthenticated paths, etc. You will heavily rely on your browser’s web console, curl, and 3rd party tools such as Burp.
Keep secrets away from code
Never commit secrets in your code. They should be handled separately in order to prevent them accidentally being shared or exposed. This allows a clear separation between your environments (typically development, staging and production).
Use a configuration file/en variable Use a configuration management module: https://www.npmjs.com/package/config
Keep your dependencies up to date
Perform data validation on everything you don't control
All user data that get into your application should be validated and escaped to avoid various kinds of injections. Or use Sqreen to protect from attacks exploiting NoSQL or SQL vulnerabilities.
Learn more about MongoDB injections: https://blog.sqreen.io/mongodb-will-not-prevent-nosql-injections-in-your-node-js-app/
Use Joi to perform data validation: https://www.npmjs.com/package/joi
Learn more about SQL injections: https://en.wikipedia.org/wiki/SQL_injection
Learn more about code injections in Node.js: [https://ckarande.gitbooks.io/owasp-nodegoat-tutorial/content/tutorial/a1-_server_side_js_injection.html](https://ckarande.gitbooks.io/owasp-nodegoat-tutorial/content/tutorial/a1-_server_side_js_injection.html)
Use a prepublish/pre-commit script to protect yourself
Before committing your code or publishing your package to a repository, you should ensure no sensitive data will be shipped. Using a pre-commit hook or a pre-publish script helps to prevent such leaks. You should particularly look for: Database credentials, API keys or configuration files.
Add a pre-publish script in your package.json file: https://docs.npmjs.com/misc/scripts
Run it unprivileged
If an attacker successfully attacks your application, having it running as a restricted-user will make it harder for the attacker to take over the host and/or to bounce to other services. Privileged users are root on Unix systems, and Administrator or System on Windows systems.
Run security linters on your code
Integrate security scanners in your CI pipeline
Use a secure development life cycle
The secure development lifecycle (SDL) is a process that helps tackle security issues at the beginning of a project. While rarely used as is, it provides useful insights at all stages of the project, from the specification to the release. It will allow you to enforce good practices at every step of the project life.
Ensure you are using security headers
Modern browsers support a set of headers dedicated to blocking certain types of attacks. Make sure you have properly implemented all security headers. Don’t forget about the Content Security Policy
Use an automated configuration management tool
An automated configuration management tool helps you ensure that your servers are updated and secured.
Your data is likely to be your business’s most precious asset. Be sure not to lose it. Implement proper backups and check for backup integrity.
MongoDB Backup: https://docs.mongodb.com/manual/core/backups/
Check your SSL / TLS configurations
Use free tools to scan your infrastructure regularly and make sure the SSL configurations are correct.
Control access on your cloud providers
The best way to protect your services (database, file storage) is to not use passwords at all. Use the built-in Identity and Access Management (IAM) functions to securely control access to your resources.
Encrypt all the things
SSL performance problems are a myth and you don’t have any good reasons not to use SSL on all your public services.
Log all the things
Infrastructure logs and application logs are your most precious allies for investigating a data breach. Make sure your logs are stored somewhere safe and central. Also make sure you whitelist- or blacklist-specific incoming data to avoid storing personally identifiable information (PII).
Manage secrets with dedicated tools and vaults
When you need to store cryptographic secrets (other than database password, TLS certificate, etc.) and perform encryption with them, you should use dedicated tools. This way the cryptographic secret never leaves the tool and you get auditing features.
Monitor your authorizations
Be proactive and be alerted when authorizations or keys binary are changed in your production.
Monitor your DNS expiration date
Just like TLS certificates, DNS can expire. Make sure you monitor your DNS expiration automatically.
Protect your servers and infrastructure from scanners
Your servers will be scanned in order to fingerprint your application and locate open services, misconfigurations, etc. You can setup tools to keep these scanners away from your servers.
Protect your users against account takeovers
Credential stuffing or brute force attacks are easy to setup. You should make sure your users are protected against account takeovers.
Renew your certificates on time
Store encrypted passwords in your configuration management
Storing passwords (like database ones) can be done on a dedicated database with restricted access. An other solution is to store them encrypted in your Source Code Management (SCM) system. That way, you just need the master key to decrypt them.
Upgrade your servers regularly
Server packages and libraries are often updated when security vulnerabilities are found. You should update them as soon as a security vulnerability is detected.
Use an immutable infrastructure
Use immutable infrastructures to avoid having to manage and update your servers.
Don’t store credit card information
Use third-party services to store credit card information to avoid having to manage and protect them.
Enforce Two-factor authentication (2FA)
Enforce 2FA on all the services used (whenever possible).
Ensure Compliance with Relevant Industry Standards
Comply to standards to ensure you follow industry best practices and answer your customer needs. But simple compliance will never protect your apps. Make sure you also take security seriously.
Have a public bug bounty program
A bug bounty program will allow external hackers to report vulnerabilities. Most of the bug bounties program allow you to offer rewards for bugs found. A lot of the reports won’t be valuable and you need security aware people inside your development teams to evaluate the bugs you receive. These programs are good additions to other security initiatives and can’t by no means be considered as enough.
Places to start:
Have a public security policy
This is a page on your corporate website describing how you plan to respond to external bug reports. You should advertise that you support responsible disclosure. Keep in mind that most of the reports that you receive aren’t relevant. Don’t freak out if you receive so called “critical disclosures”
Check out the Open Source Security Page
Keep your containers protected
Use Docker (or Kubernetes), and ensure that they are patched and secure. Use tools to automatically update and scan your containers for security vulnerabilities.
Protect against Denial Of Service (DoS)
Protect your applications against breaches
A real-time protection tool like Sqreen allows you to orchestrate your app security easily. Sqreen will enable you to get full visibility on your security, prevent data breaches, protect your customers, and stop business logic attacks. Customize your application’s response to attacks (block attack, log stack trace etc.) and get notified when something important happens.
Audit your infrastructure on a regular basis
With cloud providers, it’s easy to start instances and forget about them. You will need to create and maintain a list of your assets (servers, network devices, services exposed etc…), and review it regularly to determine if you still need them, keep them up to date, and ensure that they benefit from your latest deployments.
Detect insider threats
The most important attacks will come from attackers who have acquired larger attack surfaces. Those can be attackers with regular user accounts or users having gained access to privileged user accounts. Make sure you monitor your users to detect attackers early.
Get notified when your app is under attack
You will be attacked. Make sure you have a monitoring system in place that will detect security events targeting your application before it’s too late. Knowing when your application is starting to get massively scanned is key to stop more advanced attacks.
Monitor third party vendors