Security Best Practices
01 / 02

Injection, XSS, CSRF & Auth Fundamentals

Injection, XSS, CSRF & Auth Fundamentals

SQL Injection

// BAD — user input concatenated directly into the query
db.query(`SELECT * FROM users WHERE email = '${email}'`);

// GOOD — parameterized, input never touches the query structure
db.query('SELECT * FROM users WHERE email = $1', [email]);

XSS & CSRF

XSS: unsanitized user content rendered as HTML lets an attacker's script run in another user's browser — escape/encode output (React/Vue/Angular do this by default). CSRF: a victim's already-authenticated browser is tricked into submitting a request to a target site — defend with unpredictable CSRF tokens on state-changing requests, plus the SameSite cookie attribute.

Password Storage

const bcrypt = require('bcrypt');
const hash = await bcrypt.hash(plainPassword, 12);   // salting handled automatically
const valid = await bcrypt.compare(plainPassword, hash);
// bcrypt/Argon2, never plain SHA-256/MD5 — deliberately slow, defeats brute force

Salting ensures identical passwords produce different hashes, defeating precomputed rainbow-table attacks. Modern libraries (bcrypt, Argon2) handle salting internally.

Authentication vs. Authorization

Authentication = who you are. Authorization = what you're allowed to do. A user can be correctly authenticated yet still unauthorized for a specific resource — confusing the two is a common real bug class (see IDOR below).

Insecure Direct Object References (IDOR)

/orders/12345 without verifying the logged-in user actually owns order 12345 — an attacker just changes the ID to view someone else's data, no authentication bypass needed. Always check authorization per-object, not just per-endpoint.

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free