Node.js APIs have attack surfaces that generic web security guides do not cover. Prototype pollution lets attackers modify Object.prototype and corrupt your entire app. ReDoS (Regular Expression Denial of Service) can lock your event loop for seconds. SSRF (Server-Side Request Forgery) turns your server into an attacker proxy. This guide covers Node.js-specific threats plus the universal defenses every API needs.
⚡ TL;DR: Use helmet.js for security headers. Validate all input with Zod. Parameterized queries for SQL. Guard against prototype pollution. Use safe-regex for user-supplied patterns. Block private IPs for SSRF. Audit dependencies weekly with npm audit.
Security headers with helmet.js
const express = require('express');
const helmet = require('helmet');
const app = express();
app.use(helmet()); // Sets 11 security headers automatically:
// X-Content-Type-Options: nosniff
// X-Frame-Options: SAMEORIGIN
// Strict-Transport-Security: max-age=15552000
// Content-Security-Policy: default-src 'self'
// X-XSS-Protection: 0 (deprecated but harmless)
// Referrer-Policy: no-referrer
// Permissions-Policy: ...
// Custom CSP:
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ['self'],
scriptSrc: ['self', 'cdn.example.com'],
styleSrc: ['self', 'unsafe-inline'],
}
}));
Prototype pollution prevention
// Attack: if unsanitized user JSON reaches Object.assign or merge functions
// POST /api/user { '__proto__': { 'isAdmin': true } }
// obj.__proto__.isAdmin = true → ALL objects now have isAdmin = true!
// Vulnerable:
const settings = {};
Object.assign(settings, req.body); // Merges __proto__ pollution!
// Safe: use object without prototype for user data
const safeObj = Object.create(null);
Object.assign(safeObj, req.body);
// safeObj.__proto__ is undefined — no prototype chain to pollute
// Or: validate and strip dangerous keys
const { ['__proto__']: _, ['constructor']: __, ...safe } = req.body;
// Use libraries that protect against it:
// deepmerge: safe merge ✓
// lodash.merge: vulnerable ✗ (use lodash.mergewith instead)
ReDoS — event loop DoS via regex
// ReDoS: catastrophic backtracking in regex freezes event loop
// VULNERABLE regex (exponential backtracking):
const evil = /^(a+)+$/; // Try: 'aaaaaaaaaaaaaaab' → hangs for seconds!
// Safe alternatives:
// 1. Use safe-regex to detect vulnerable patterns
const safeRegex = require('safe-regex');
safeRegex(/^(a+)+$/); // false = UNSAFE
// 2. Add timeout to regex execution
const { execFileSync } = require('child_process');
// Or use: node-re2 (Google's RE2 engine — guaranteed O(n))
const RE2 = require('re2');
const re = new RE2('^(a+)+$'); // RE2 has no catastrophic backtracking
// 3. Never use user-supplied regex patterns directly
SSRF prevention
const axios = require('axios');
const { isPrivateIp } = require('private-ip');
const { URL } = require('url');
async function fetchExternalUrl(userSuppliedUrl) {
const url = new URL(userSuppliedUrl); // Throws on invalid URL
// Block private/internal IPs
if (isPrivateIp(url.hostname)) {
throw new Error('Access to private addresses not allowed');
}
// Only allow specific protocols
if (!['http:', 'https:'].includes(url.protocol)) {
throw new Error('Only HTTP/HTTPS allowed');
}
return axios.get(url.toString(), {
timeout: 5000,
maxRedirects: 3
});
}
- ✅ helmet.js on every Express app — security headers in one line
- ✅ Validate all input with Zod before touching it
- ✅ Object.create(null) for user-data containers — no prototype
- ✅ safe-regex or RE2 for any user-supplied patterns
- ✅ Block private IPs for any server-side URL fetching
- ✅ npm audit weekly + Dependabot or Snyk for automated alerts
- ❌ Never pass user input to eval(), exec(), or spawn() with shell:true
- ❌ Never log sensitive data (passwords, tokens, PII)
Node.js security builds on the API security guide — that covers universal web API threats, this covers Node.js-specific ones. External reference: OWASP Node.js Security Cheat Sheet.
Recommended Reading
→ Designing Data-Intensive Applications — The essential book every senior developer needs.
→ The Pragmatic Programmer — Timeless engineering wisdom for writing better code.
Affiliate links. We earn a small commission at no extra cost to you.
Free Weekly Newsletter
🚀 Don’t Miss the Next Cheat Code
Join 1,000+ senior developers getting expert JS, Python, AWS and system design secrets weekly.
Discover more from CheatCoders
Subscribe to get the latest posts sent to your email.
