Security is a critical aspect of any Node.js application. Without proper security measures, your app can be vulnerable to attacks like XSS, CSRF, SQL/NoSQL injection, brute force, and more.
In this guide, we'll explore 10 must-use security packages that help protect your Node.js application and explain why they are important.
1οΈβ£ Helmet - Protect Against Common Web Vulnerabilities
πΉ Why use it?
By default, Express.js doesn't secure HTTP headers, making your app susceptible to attacks like Clickjacking, Cross-Site Scripting (XSS), MIME sniffing, and more.
πΉ How does it help?
helmet
sets secure HTTP headers to mitigate common web vulnerabilities.
πΉ How to use it?
const express = require("express");
const helmet = require("helmet");
const app = express();
app.use(helmet()); // Enables secure HTTP headers
app.get("/", (req, res) => res.send("Secure App"));
app.listen(3000, () => console.log("Server running on port 3000"));
β Protects against common attacks by securing HTTP response headers
2οΈβ£ dotenv - Secure Environment Variables
πΉ Why use it?
Never hardcode sensitive data like API keys, database credentials, or JWT secrets in your source code. .env
files keep these values secure and separate.
πΉ How to use it?
- Install
dotenv
:
npm install dotenv
- Create a
.env
file:
SECRET_KEY=my_super_secret_key
- Load it in your code:
require("dotenv").config();
console.log(process.env.SECRET_KEY); // Securely access environment variables
β Prevents exposing sensitive information in source code
3οΈβ£ CORS - Control Cross-Origin Requests
πΉ Why use it?
By default, web browsers block requests from other domains for security reasons. CORS (Cross-Origin Resource Sharing) lets you allow or restrict which origins can access your API.
πΉ How to use it?
const cors = require("cors");
app.use(cors({ origin: "https://yourdomain.com" })); // Only allow this domain
β Prevents unauthorized cross-origin API requests
4οΈβ£ express-rate-limit - Prevent Brute Force Attacks
πΉ Why use it?
Attackers can flood your API with requests, causing DDoS (Denial-of-Service) attacks or brute force login attempts. Rate limiting prevents this.
πΉ How to use it?
const rateLimit = require("express-rate-limit");
const limiter = rateLimit({ windowMs: 15 * 60 * 1000, max: 100 }); // 100 requests per 15 minutes
app.use(limiter);
β Protects against API abuse and brute force attacks
5οΈβ£ express-mongo-sanitize - Prevent NoSQL Injection
πΉ Why use it?
If you're using MongoDB, attackers can inject malicious queries through user input to manipulate your database.
πΉ How to use it?
const mongoSanitize = require("express-mongo-sanitize");
app.use(mongoSanitize()); // Cleans input data to prevent NoSQL injection
β Secures your MongoDB database against injection attacks
6οΈβ£ xss-clean - Prevent Cross-Site Scripting (XSS)
πΉ Why use it?
If user input isnβt sanitized, attackers can inject malicious scripts that steal data or hijack user sessions.
πΉ How to use it?
const xss = require("xss-clean");
app.use(xss()); // Sanitizes input to remove XSS vulnerabilities
β Prevents malicious scripts from being executed on the client side
7οΈβ£ bcryptjs - Hash Passwords Securely
πΉ Why use it?
Never store passwords in plaintext! bcrypt
securely hashes passwords before storing them.
πΉ How to use it?
const bcrypt = require("bcryptjs");
const hashPassword = async (password) => {
const salt = await bcrypt.genSalt(10);
return await bcrypt.hash(password, salt);
};
hashPassword("mySecurePassword").then(console.log);
β Ensures passwords are securely stored and encrypted
8οΈβ£ jsonwebtoken (JWT) - Secure Authentication
πΉ Why use it?
JSON Web Tokens (JWT) allow secure authentication without storing sessions on the server.
πΉ How to use it?
const jwt = require("jsonwebtoken");
const token = jwt.sign({ userId: 123 }, "secretKey", { expiresIn: "1h" });
console.log(token);
β Ensures secure user authentication with signed tokens
9οΈβ£ hpp - Prevent HTTP Parameter Pollution
πΉ Why use it?
Hackers can manipulate query parameters in URLs to exploit your API.
πΉ How to use it?
const hpp = require("hpp");
app.use(hpp()); // Prevents duplicate or malicious query parameters
β Prevents attackers from sending multiple parameters to manipulate requests
π csurf - CSRF Protection
πΉ Why use it?
CSRF (Cross-Site Request Forgery) tricks users into making unauthorized requests on a web app. csurf
protects against this.
πΉ How to use it?
const csurf = require("csurf");
app.use(csurf()); // Enables CSRF protection
β Prevents unauthorized actions from being performed on behalf of users
π― Conclusion: Secure Your Node.js App Today!
Security is a must-have in any Node.js project. By integrating these 10 security packages, you can protect your app from common threats like XSS, CSRF, NoSQL injection, and brute force attacks.
π₯ Summary of Security Packages:
Security Issue | Package | Solution |
---|---|---|
HTTP vulnerabilities | helmet | Secure HTTP headers |
Leaked credentials | dotenv | Store sensitive data securely |
Unauthorized API requests | cors | Restrict cross-origin requests |
Brute force attacks | express-rate-limit | Limit requests per IP |
NoSQL injection | express-mongo-sanitize | Prevent MongoDB injection |
XSS attacks | xss-clean | Sanitize user input |
Weak password storage | bcryptjs | Hash passwords securely |
Authentication security | jsonwebtoken (JWT) | Secure user authentication |
URL query manipulation | hpp | Prevent HTTP parameter pollution |
CSRF attacks | csurf | Protect against CSRF |
π Bonus Security Tips!
π― Use Centralized Logging & Alerts
Instead of just logging errors in a file, use a centralized logging system to detect anomalies and attacks in real time.
π Use Winston with a Logging Service (like Loggly, Datadog, or AWS CloudWatch):
const winston = require("winston");
const { Loggly } = require("winston-loggly-bulk");
const logger = winston.createLogger({
level: "info",
format: winston.format.json(),
transports: [
new winston.transports.Console(),
new Loggly({
token: "YOUR_LOGGLY_TOKEN",
subdomain: "your-subdomain",
tags: ["Node.js", "Security"],
json: true,
}),
],
});
logger.info("Application started");
logger.error("Security alert! Unauthorized access attempt.");
β Sends logs to a remote server, helping detect hacking attempts.
Let me know in the comments if you have any questions!
-> Follow for more!
Top comments (4)
you might like dmno.dev - it's a secret management toolkit that has a lot of security features, like log redaction, and leak prevention. Also can help you avoid ever having secrets sitting in plaintext .env files.
Thanks for the recommendation, Theo! dmno.dev looks interesting. How does it handle secret rotation and access control compared to tools like Doppler or HashiCorp Vault? Also, does it integrate well with popular deployment platforms like Vercel or Netlify?
It integrates really nicely with Vercel, Netlify, Cloudflare, etc. We have specific integration packages that help provide some additional features for certain platforms - at minimum pre-made schemas of the env vars those platforms inject - and in some cases much more (like a fancy wrapper around Cloudflare's wrangler).
Our model pulls from many different sources (1password, encrypted files, etc) so the tool itself does not have direct access to handle things like secret rotation or dynamic secrets, and the access control model depends on the source. For example the encrypted vault is just a single key, so you would share that key with your team. For 1password, local dev usually uses the 1Password app, while deployed envs use service account tokens. You can segment those into multiple vaults however you need to...
But we are working on our own hosted secret backend which would be able to handle rotation/etc, to provide some of those features. Things obviously get much trickier once you have access to the decrypted values - which you need to some degree to do rotation/etc. We could also easily build plugins that connect to Doppler/Vault (we already have one for Infisical) to still provide the rest of what DMNO offers - validations, type-safety, leak detection, etc.
Happy to help you get it set up and try it out :) Would love to hear what you think.
That sounds awesome! I really like how DMNO integrates seamlessly with platforms like Vercel, Netlify, and Cloudflare, and the pre-made schemas for env vars are a great touch. The flexibility of pulling secrets from different sources like 1Password and encrypted files is super useful, especially for teams with varying workflows.
The upcoming hosted secret backend sounds exciting! Rotation and dynamic secrets are definitely tricky, but having a native solution for that would make DMNO even more powerful. Also, the potential for Doppler/Vault plugins is a smart moveβit keeps things modular while still leveraging DMNOβs strengths in validation, type safety, and leak detection.
Iβd love to try it out and see how it fits into my stack! The type of safety and leak detection alone makes it really appealing. Iβll take a deeper look and let you know my thoughts after testing it. Appreciate the offer to help with setup! π