What are common Node.js security vulnerabilities and how do you mitigate them?
Quick Answer
Key risks include injection (SQL/NoSQL/command), XSS, insecure dependencies, secrets in code, missing security headers, and unvalidated input. Mitigate with parameterized queries, input validation/sanitization, helmet for headers, CORS/rate limiting, dependency auditing (npm audit), and keeping secrets in environment variables.
Detailed Answer
Answer:
Node apps face the usual web risks plus a large supply-chain surface via node_modules.
Common vulnerabilities and fixes:
- Injection (SQL/NoSQL/command): never build queries by string concatenation.
// ❌ SQL injection
db.query(`SELECT * FROM users WHERE id = ${req.params.id}`);
// ✅ Parameterized
db.query('SELECT * FROM users WHERE id = $1', [req.params.id]);
For child_process, avoid exec with user input; use execFile/spawn with an args array.
-
Cross-site scripting (XSS): escape/encode output; sanitize any HTML (
DOMPurifyon rendered content); set a Content-Security-Policy. -
Insecure dependencies (supply chain): run
npm audit, pin versions with a lockfile, usenpm ci, and tools like Dependabot/Snyk. Most Node vulns come from transitive deps. -
Secrets in code: keep credentials in environment variables / a secrets manager, never in the repo. Add
.envto.gitignore. -
Missing security headers: use helmet to set sensible defaults (HSTS, X-Content-Type-Options, CSP, etc.).
app.use(require('helmet')());
-
Unvalidated input / mass assignment: validate and whitelist fields (
zod,joi); don't blindly spreadreq.bodyinto DB models. -
CORS & rate limiting: restrict origins with the
corsmiddleware; throttle withexpress-rate-limitto blunt brute-force/DoS. -
ReDoS / large payloads: cap body size (
express.json({ limit: '100kb' })), avoid catastrophic regexes.
Baseline checklist: HTTPS everywhere, helmet, input validation, parameterized queries, npm audit in CI, secrets in env, least-privilege DB users, and up-to-date Node.