gap·map

Server-side security

[ middle depth ]

How SQL injection happens and how to stop it

Injection happens whenever user input is concatenated into a query string, so the input gets parsed as SQL instead of treated as data. The fix is a parameterized query: the driver sends the SQL text and the values on separate channels, and a bound value can never change the parse tree.

// vulnerable: input becomes SQL
db.query(`SELECT * FROM users WHERE email = '${email}'`);
// safe: $1 is bound as data, not parsed
db.query("SELECT * FROM users WHERE email = $1", [email]);

One trap survives the switch to placeholders: they bind values only, never identifiers. A column name, a table name, or ORDER BY col ASC cannot be a parameter.

// still injectable even though category is bound
`... WHERE category = $1 ORDER BY ${sort}`;

For anything dynamic that is not a value, map the user's choice through a server-side allowlist to a hardcoded string. wrong "we use an ORM, so injection is impossible." ORMs parameterize their generated queries, but raw-SQL escape hatches and string-built WHERE/ORDER BY fragments interpolate exactly like hand-written code.

How to defend against SSRF

Server-Side Request Forgery is when your server fetches a URL the user controls: a webhook, an image proxy, a link-preview fetcher. Point that fetch at http://169.254.169.254/ and on a cloud host it returns instance metadata, often including temporary IAM credentials. Point it at http://localhost:6379 and it reaches internal services the network firewall trusts.

Defend with an allowlist of scheme, host, and port, block private and link-local ranges, and disable redirects (or re-validate every hop). Denylisting localhost and 127.0.0.1 is not enough: 0.0.0.0, [::1], and 2130706433 (decimal) all reach loopback.

How to store passwords and secrets

Hash passwords with a slow, salted key-derivation function: Argon2id first choice, bcrypt or scrypt acceptable. The salt is random per password and stored next to the hash; it defeats precomputed rainbow tables and is not secret.

wrong "SHA-256 with a salt is fine." SHA-256 is built to be fast, so a GPU tries billions of guesses per second. The salt stops rainbow tables but does nothing against brute force. Slowness is the point of a password hash.

Secrets like database passwords and API keys never belong in source code or a committed .env. Environment variables beat hardcoding, but at scale use a secrets manager (Vault, AWS or GCP Secret Manager) for access control, an audit trail, and rotation.

Encryption at rest versus in transit

TLS encrypts data in transit, on the wire between client and server. Encryption at rest (full-disk or column-level, typically AES-256) protects data sitting in storage. They cover different threats, a stolen disk versus a sniffed connection, so production systems generally want both.

[ senior depth ]

Why prepared statements are structurally safe

The guarantee is about ordering. With a prepared statement the database parses and plans the query text while the values are still placeholders, so by the time your value arrives it is bound into an already-compiled plan as a typed literal. There is no parse step left for it to influence. Escaping is the weaker cousin: it is a blocklist of characters applied to a string, and it breaks on charset edges, numeric contexts, and the backslash. Bind values, do not escape them.

The bug that survives a codebase-wide switch to placeholders is second-order injection: input is stored safely, then a different code path concatenates the stored value into a query later. Parameterize every query, not only the ones that read directly from the request. And placeholders bind values only, so every dynamic identifier (table, column, ASC/DESC, and in some drivers LIMIT) still needs an allowlist mapping to hardcoded strings.

How to defend SSRF against DNS rebinding

"Validate the URL, then fetch it" has a race: the hostname can re-resolve between the check and the connection. An attacker returns an allowlisted IP for the validation lookup and a link-local address for the connect lookup. Close it by resolving once, validating the resolved IP against the allowlist, then connecting to that pinned IP.

On cloud hosts the prize is the metadata endpoint. IMDSv2 blunts a naive GET-only SSRF because it requires a PUT request to mint a session token first. The durable control is at the network layer: deny outbound from the app subnet except through an allowlisted egress proxy, so a bypassed input check still has nowhere to go.

Password hashing internals interviewers probe

Pick a work factor that costs about 250 to 500 ms on your verification server, re-benchmark yearly, and store the algorithm and cost inside the hash string so you can upgrade a user's hash on their next successful login. bcrypt silently truncates input at 72 bytes, which bites if you prepend a pepper or pre-hash: a long password can push the pepper past the cut. When input length matters, reach for Argon2id.

Salt and pepper are different tools. The salt is public, per password, stored with the hash, and defeats rainbow tables. The pepper is a single application-side secret held in a KMS or HSM, never in the database, so a database-only leak still cannot crack the hashes. Its cost is rotation: version the pepper and re-hash on login.

Encryption at rest tiers and envelope encryption

wrong "encryption at rest protects me from an attacker who compromised my app." Full-disk encryption only defends stolen media; a running process reads plaintext. Field-level encryption narrows the exposure further. Envelope encryption is the pattern to name: a per-record data key (DEK) encrypts the data, a KMS-held key-encryption key (KEK) wraps the DEK, so you rotate the KEK without re-encrypting data and the plaintext key never leaves the KMS. From the server side the OWASP Top 10 collapses to a few graded reflexes: parameterize (A03), enforce authorization at the data layer against IDOR (A01, see auth-backend), hash and encrypt correctly (A02), and lock down SSRF and metadata (A10).

beta

The interviewer part is in the works.

The diagnostic, personal maps, and AI mock interviews are being finished right now. The notes stay free either way. Leave an email and you'll get the first-cohort invite, plus a month of Pro when it opens.

builds on

more Backend Security