SQL Injection
Never concatenate user input into queries. Use parameterized queries:
// VULNERABLE
const q = `SELECT * FROM users WHERE name = '${req.body.name}'`
// SAFE — use your ORM/driver's parameterized form
const q = 'SELECT * FROM users WHERE name = $1'
client.query(q, [req.body.name])XSS (Cross-Site Scripting)
Sanitize any user content before rendering it in HTML. Libraries like DOMPurify (browser) or sanitize-html (server) strip malicious scripts.
CSRF (Cross-Site Request Forgery)
A malicious site tricks a logged-in user into making a request to your API. Mitigations:
SameSite=Strict or SameSite=Lax cookiescsurf npm package handles this for ExpressHelmet.js — sets secure HTTP headers in one line:
const helmet = require('helmet')
app.use(helmet())
// Sets X-Content-Type-Options, X-Frame-Options, Strict-Transport-Security, etc.Rate limiting
const rateLimit = require('express-rate-limit')
const limiter = rateLimit({ windowMs: 60_000, max: 100 })
app.use(limiter)SQL Injection
Never concatenate user input into queries. Use parameterized queries:
// VULNERABLE
const q = `SELECT * FROM users WHERE name = '${req.body.name}'`
// SAFE — use your ORM/driver's parameterized form
const q = 'SELECT * FROM users WHERE name = $1'
client.query(q, [req.body.name])XSS (Cross-Site Scripting)
Sanitize any user content before rendering it in HTML. Libraries like DOMPurify (browser) or sanitize-html (server) strip malicious scripts.
CSRF (Cross-Site Request Forgery)
A malicious site tricks a logged-in user into making a request to your API. Mitigations:
SameSite=Strict or SameSite=Lax cookiescsurf npm package handles this for ExpressHelmet.js — sets secure HTTP headers in one line:
const helmet = require('helmet')
app.use(helmet())
// Sets X-Content-Type-Options, X-Frame-Options, Strict-Transport-Security, etc.Rate limiting
const rateLimit = require('express-rate-limit')
const limiter = rateLimit({ windowMs: 60_000, max: 100 })
app.use(limiter)