Study notes · 9% of the exam

Node.js Security

Node.js security is mostly about treating every input as hostile on a single shared thread: keep code and data separate, never let user input choose paths, prototypes or destinations, and assume dependencies can be malicious.

Key points

  1. 1

    Use parameterized queries, execFile with argument arrays (plus a -- separator), and schema validation that enforces types, so input can never become code, operators or options.

  2. 2

    Prototype pollution comes from merging untrusted objects: block __proto__, constructor and prototype, use Map or Object.create(null), and check permissions with Object.hasOwn.

  3. 3

    Resolve and contain file paths with path.resolve plus path.relative; a string startsWith(base) check is fooled by sibling folders.

  4. 4

    Anything CPU-bound on the event loop, such as a catastrophic regex or a huge JSON body, blocks every user. Limit input sizes and timeouts, and use linear-time regex engines for untrusted patterns.

  5. 5

    SSRF defences must check the resolved IP (including IPv4-mapped IPv6), pin the connection to it, and re-check redirects.

  6. 6

    Use crypto.randomBytes/randomUUID for tokens, argon2id or bcrypt for passwords, AES-GCM with a fresh IV for encryption, and timingSafeEqual on equal-length buffers.

  7. 7

    Supply-chain risk is real: lockfiles plus npm ci, --ignore-scripts, scoped internal packages, provenance checks and few dependencies. npm audit only knows reported issues.

Common traps

  • JSON.stringify output is not HTML-safe: </script> inside a string ends an inline script tag.

  • --disable-proto and the vm module are defence in depth at best; neither stops a determined attacker on its own.

  • SameSite=Lax still sends cookies on top-level GET navigations, so state-changing GET endpoints stay forgeable.

Test yourself on Node.js Security

Ten questions, with the answer and explanation after each one.