core practice · coding problem

Parameterise instead of escaping

Implement buildQuery(table, filters) returning { text, values }: a parameterised SQL string using $1, $2 … placeholders in order, plus the values array. Column names come from a fixed ALLOWED set — reject anything else by throwing. Never interpolate a value into the string.

The mechanism

Almost every one of these is the same bug: data crossing into a place where it is interpreted as code or as authority. Injection (SQLi, XSS) is untrusted input reaching an interpreter, and the fix is never escaping-by-hand but parameterisation and contextual output encoding. CSRF is different in kind — a confused deputy, where the browser helpfully attaches your cookies to a request your site did not initiate, which is why the defence is an unguessable token or SameSite rather than validation. CORS is not a defence at all; it relaxes the same-origin policy, so a permissive CORS header removes protection rather than adding it.

Study Web Security Basics

Expected evidence

buildQuery('users', {name:'ann', age:30}) -> { text: 'SELECT * FROM users WHERE name = $1 AND age = $2', values: ['ann', 30] }

Try this drill in the practice workspace →

Hints when you need them
  • Values are never concatenated. Identifiers cannot be parameterised, which is exactly why they need an allowlist.
  • A value containing a quote must end up in `values` untouched, not escaped into `text`.

Watch for these mistakes

  • Treating CORS as a security control — it grants access, it does not restrict it
  • Escaping output once globally instead of per context; HTML, attribute, URL and JS contexts need different encodings
  • Blocklisting dangerous input instead of parameterising the query
  • Storing session tokens in localStorage, which is readable by any XSS you ever ship

Check the sources

Browse all practice briefs