All posts
SecurityMay 30, 2026·12 min read

Top 25 Node.js Security Best Practices

SQL injection, prototype pollution, path traversal, insecure deserialization — plus 21 more. A comprehensive security checklist for every Node.js API in production.

Authentication & Authorization

1. Hash passwords with bcrypt or Argon2. Never store plaintext or MD5/SHA passwords. Use bcrypt (work factor 12+) or Argon2id.

2. Use parameterized queries — always. The only way to prevent SQL injection. Never concatenate user input into SQL strings.

// ✗ Vulnerable
const query = `SELECT * FROM users WHERE email = '${email}'`;

// ✓ Safe
const user = await db.query('SELECT * FROM users WHERE email = $1', [email]);

3. Validate and sanitize all input. Use zod or joi to validate request bodies, query params, and path parameters. Reject malformed input early.

4. Implement rate limiting on authentication endpoints. Brute force against /login without rate limiting is trivial. 5 attempts per 15 minutes is a reasonable default.

5. Use helmet for security headers. HSTS, CSP, X-Frame-Options, and 9 more with one line.

Secrets & Configuration

6. Never commit secrets to git. Use .gitignore for .env files. Use a secrets scanner in CI (truffleHog, git-secrets).

7. Rotate secrets regularly. Database passwords, API keys, and JWT secrets should have a rotation policy. Use a secrets manager (AWS Secrets Manager, HashiCorp Vault) in production.

8. Principle of least privilege for database users. Your app's DB user should only have SELECT, INSERT, UPDATE, DELETE on the tables it needs. Never connect as the superuser.

Dependencies

9. Run npm audit in CI. Block merges with critical vulnerabilities.

10. Pin dependency versions. Use package-lock.json or npm ci in production builds. Avoid ^ ranges in critical packages.

11. Minimize dependencies. Every package is an attack surface. Before adding a dependency, ask if you really need it.

HTTP Security

12. Enforce HTTPS everywhere. Redirect HTTP to HTTPS. Set Strict-Transport-Security with a long max-age.

13. Validate Content-Type headers. An attacker sending JSON as text/plain can bypass middleware that only parses JSON. Check the content type.

14. Limit request body size. Default Express body-parser limit is 100kb. Set it to what your API actually needs. A 10MB JSON body can OOM your server.

app.use(express.json({ limit: '1mb' }));

15. Disable X-Powered-By. Don't advertise your tech stack. app.disable('x-powered-by') or use helmet.

Node.js Specific

16. Prevent prototype pollution. Never merge user input directly into objects. Use Object.create(null) for lookup maps, and validate merge operations.

17. Avoid path traversal. When using file paths from user input, always resolve and validate against a whitelist of allowed directories.

import path from 'path';

const BASE_DIR = '/app/uploads';
const requestedPath = path.resolve(BASE_DIR, req.params.filename);
if (!requestedPath.startsWith(BASE_DIR)) {
  return res.status(403).send('Forbidden');
}

18. Use a non-root user in containers. If your app is compromised and running as root, the attacker has root on the container. Run as a dedicated non-root user.

19. Keep Node.js updated. Run the current LTS release. Use Dependabot or Renovate to automate updates.

20. Avoid eval and Function(). These execute arbitrary code. If you find yourself needing them, there's almost always a better approach.

API Design

21. Use CORS properly. Don't set Access-Control-Allow-Origin: * for authenticated APIs. Whitelist specific origins.

22. Avoid leaking stack traces. In production, catch errors and return a generic message. Log the full error internally. Never send stack traces to clients.

23. Implement CSRF protection for cookie-based auth. Use SameSite=Strict cookies or a CSRF token for state-changing endpoints.

Infrastructure

24. Scan your Docker images. Use docker scout, Trivy, or Snyk to scan images for OS-level CVEs before pushing to production.

25. Implement audit logging. Log authentication events, privilege changes, and data access for sensitive resources. These logs are critical for incident response and compliance.

Ready to put this into practice?

Deploy your Node.js app to production in minutes — zero YAML, automatic CI/CD, and HTTPS included.