</>StackKit
</>StackKit

Developer tutorials & guides

Security lock on a circuit board
Security

Node.js Security Best Practices: Protect Your App in 2025

Essential Node.js security practices including input validation, SQL injection prevention, rate limiting, JWT best practices, and dependency auditing.

L
Leila Hassan
April 2, 20259 min read
#nodejs#security#backend#express

Security Is Not Optional

Every Node.js app that touches the internet is a target. Security isn't an afterthought — it's a first-class concern from day one. This guide covers the most important security practices for Node.js/Express applications.


1. Validate and Sanitize All Input

Never trust input from users, APIs, or databases. Use a validation library like Zod:

import { z } from 'zod';

const CreateUserSchema = z.object({
  name: z.string().min(1).max(100).trim(),
  email: z.string().email().toLowerCase(),
  age: z.number().int().min(0).max(150),
});

app.post('/users', (req, res) => {
  const result = CreateUserSchema.safeParse(req.body);
  if (!result.success) {
    return res.status(400).json({ errors: result.error.flatten() });
  }
  // result.data is now safe to use
});

2. Use Parameterized Queries (Never Template SQL)

// NEVER do this — SQL injection vulnerability
const user = await db.query(
  `SELECT * FROM users WHERE email = '${email}'`
);

// Always use parameterized queries
const user = await db.query(
  'SELECT * FROM users WHERE email = $1',
  [email]
);

// Or use an ORM (Prisma, Drizzle, TypeORM)
const user = await prisma.user.findUnique({ where: { email } });

3. Set Security Headers with Helmet

npm install helmet
import helmet from 'helmet';
app.use(helmet());

Helmet sets a dozen security headers automatically: Content-Security-Policy, X-Frame-Options, X-XSS-Protection, and more.


4. Rate Limiting

Prevent brute force and DoS attacks:

import rateLimit from 'express-rate-limit';

const authLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 10, // max 10 attempts per window
  message: 'Too many login attempts. Please try again later.',
});

app.post('/auth/login', authLimiter, loginHandler);

5. Secure JWT Handling

import jwt from 'jsonwebtoken';

// Sign with RS256 (asymmetric) for production
const token = jwt.sign(
  { userId: user.id, role: user.role },
  process.env.JWT_PRIVATE_KEY,
  {
    algorithm: 'RS256',
    expiresIn: '15m',   // Short-lived access tokens
    issuer: 'your-app',
  }
);

// Store refresh tokens in httpOnly cookies — not localStorage
res.cookie('refresh_token', refreshToken, {
  httpOnly: true,
  secure: true,
  sameSite: 'strict',
  maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days
});

6. Hash Passwords with bcrypt

import bcrypt from 'bcryptjs';

// Hash on registration
const hash = await bcrypt.hash(password, 12); // cost factor 12

// Verify on login
const isValid = await bcrypt.compare(inputPassword, storedHash);

Never store plain text passwords or use MD5/SHA1 for passwords.


7. Environment Variables — Never Hardcode Secrets

// Bad — hardcoded secrets
const apiKey = 'sk-abc123def456';

// Good
const apiKey = process.env.OPENAI_API_KEY;
if (!apiKey) throw new Error('OPENAI_API_KEY not set');

Use a .env file locally and a secrets manager (AWS Secrets Manager, Doppler, Vercel env vars) in production. Add .env to .gitignore.


8. Audit Dependencies Regularly

npm audit              # check for known vulnerabilities
npm audit fix          # auto-fix where possible
npx snyk test          # more comprehensive scanning

Run npm audit in CI so you catch new vulnerabilities before they ship.


9. Avoid eval() and Function()

// Never do this — remote code execution risk
eval(userInput);
new Function(userInput)();

10. Use HTTPS Everywhere

In production, always terminate TLS. Use Nginx, a load balancer, or Cloudflare in front of your Node.js server. Never serve credentials over HTTP.


Conclusion

Security is a checklist you work through systematically: validate input, parameterize queries, set security headers, rate limit, handle JWTs carefully, hash passwords, keep secrets out of code, audit deps. Do these 10 things and you'll have eliminated the vast majority of common vulnerabilities.

#nodejs#security#backend#express