Security Checklist

The Basics You Cannot Skip

Security Checklist

The minimum-viable security checklist for a Node web app. Each item prevents a common attack class.

5 min read Level 2/5 #nodejs#security#helmet
What you'll learn
  • Apply Helmet, CORS, rate-limit
  • Avoid the OWASP Top 10 in Node
  • Keep deps updated

The biggest security wins are the cheapest. Below is a ship-it-tomorrow checklist for a Node web app.

✅ Use Helmet

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

One line sets ~12 security headers: CSP, HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, etc.

✅ Validate All Input

Use Zod (covered earlier) on every request body, every query string. Untrusted input is the root of most vulnerabilities.

✅ Parameterized SQL — Never Concat

// NEVER
db.query(`SELECT * FROM users WHERE email = '${email}'`);

// ALWAYS
db.query("SELECT * FROM users WHERE email = $1", [email]);

Same for shell commands — use execFile([...args]), never exec with concatenation.

✅ Hash Passwords with bcrypt/argon2

No plaintext. No sha256. Use a slow KDF.

HttpOnly + Secure + SameSite=Lax on session cookies. Always.

✅ Rate-Limit Login Endpoints

5 attempts per 15 minutes per IP. Prevents brute force.

✅ CORS Allow-List

Never Access-Control-Allow-Origin: * with credentials. List the origins you actually trust.

✅ Don’t Expose Stack Traces

In production, the error response should be generic. Stack traces land in your logs, not on the client.

✅ Keep Deps Updated

npm audit
npm audit fix

Better: use Dependabot or Renovate to open PRs as updates land. Fewer surprises.

✅ Lock Down Env Vars

Never log them. Never commit .env. Rotate compromised secrets immediately.

✅ HTTPS Everywhere

In production, HTTPS only. Set HSTS. The reverse proxy or CDN handles this.

✅ Watch for SSRF

If your server fetches URLs the user provides, validate that the URL doesn’t point to localhost, 169.254.169.254 (AWS metadata), or internal IPs.

import { URL } from "node:url";

function isSafeURL(input) {
  const u = new URL(input);
  if (!["http:", "https:"].includes(u.protocol)) return false;
  if (["localhost", "127.0.0.1", "0.0.0.0", "169.254.169.254"].includes(u.hostname)) return false;
  return true;
}

The OWASP Top 10

If you have time for one external resource: read the OWASP Top 10. Each entry is a vulnerability class. Make sure none apply to your app.

Going Further →