One page
Web application security cheat sheet
What to keep at hand. If a line is not clear, go back to the matching lesson in the course.
Open the course: Web application securityInjection
| What | How |
|---|---|
| SQL with a value | pool.query("... WHERE id = $1", [id]) |
| Column or sort order | allowlist, not a placeholder |
| Prisma, raw SQL | $queryRaw`...${x}`, not $queryRawUnsafe |
| External program | execFile("cmd", [arg]), not exec |
| MongoDB filter | typeof value === "string" |
XSS and CSRF
| What | How |
|---|---|
| Output text | textContent, not innerHTML |
| HTML is required | DOMPurify.sanitize(html) |
| CSP | script-src 'nonce-...' 'strict-dynamic'; object-src 'none' |
| Session cookie | HttpOnly; Secure; SameSite=Lax |
| State changing form | CSRF token + Origin check |
Authentication and secrets
| What | How |
|---|---|
| Password hash | Argon2id: 19 MiB, t=2, p=1 |
| Comparing secrets | crypto.timingSafeEqual(a, b) |
| Login limit | per account and per IP |
| Best second factor | passkey (WebAuthn) |
| A secret leaked | revoke, issue a new one, check the logs |
| JWT key rotation | kid in the header, two keys during the transition |
Headers, SSRF, dependencies
| What | How |
|---|---|
| HTTPS only | Strict-Transport-Security: max-age=63072000 |
| Do not guess the type | X-Content-Type-Options: nosniff |
| No iframes | frame-ancestors 'none' |
| CORS with cookies | Origin allowlist + Vary: Origin |
| URL from the user | host allowlist, no redirects |
| Install in CI | pnpm install --frozen-lockfile |