DEV Community

Cover image for 13 Security Questions Every JavaScript Interview Asks — and the ESLint Rule That Answers Each in CI
Ofri Peretz
Ofri Peretz

Posted on • Edited on • Originally published at ofriperetz.dev

13 Security Questions Every JavaScript Interview Asks — and the ESLint Rule That Answers Each in CI

I've interviewed 50+ backend and full-stack engineers. Security questions show
up in almost every loop now — even for roles that aren't labeled "security."
Here are the 13 questions that come up the most, each with the answer in one
breath, the bad-vs-good code, the CWE, and — the part most cheat-sheets skip —
the ESLint rule that enforces it so you never ship the bad version.

The best answer to "how do you stay current?" isn't "I read CVEs." It's "I
enforce these in CI." This is how.


The fundamentals (asked ~90% of the time)

1. SQL Injection

db.query(`SELECT * FROM users WHERE id = ${userId}`); // ❌
db.query("SELECT * FROM users WHERE id = $1", [userId]); // ✅
Enter fullscreen mode Exit fullscreen mode

Say: "Parameterized queries separate data from code." CWE-89. Enforced by
pg/no-unsafe-query.

2. XSS (and its three types)

Stored (saved to the DB), reflected (echoed from the URL), and DOM (written by
client JS). The browser-side fix is the same reflex:

element.innerHTML = userInput; // ❌
element.textContent = userInput; // ✅
Enter fullscreen mode Exit fullscreen mode

CWE-79. Enforced by browser-security/no-innerhtml.

3. Password storage

crypto.createHash("md5").update(password); // ❌
await bcrypt.hash(password, 12); // ✅
Enter fullscreen mode Exit fullscreen mode

Say: "bcrypt or argon2, per-user salt, a work factor." CWE-916. The weak
hash is caught by node-security/no-weak-hash-algorithm.


Intermediate (asked ~70% of the time)

4. CSRF

Cross-Site Request Forgery rides an authenticated user's cookies to perform
actions they didn't intend. Prevention: synchronizer tokens, SameSite
cookies, origin checks. CWE-352. Enforced by
express-security/require-csrf-protection.

5. The Same-Origin Policy

Browsers isolate by origin (scheme + host + port). The controlled relaxations are
CORS, postMessage, and (legacy) JSONP — and an over-broad CORS policy
re-opens everything (CWE-942). browser-security/no-permissive-cors catches
the wildcard.

6. Timing attacks

if (userToken === secretToken) {
} // ❌ leaks via comparison time
crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b)); // ✅ constant-time
Enter fullscreen mode Exit fullscreen mode

CWE-208. Enforced by node-security/no-timing-unsafe-compare.

7. JWTs

Verify the signature, check exp, never accept algorithm: "none", and store in
an httpOnly cookie — not localStorage. CWE-347 for the none bypass
(jwt/no-algorithm-none); the storage mistake is browser-security/no-jwt-in-storage.


Advanced (asked ~50% of the time)

8. Prototype pollution

obj[key] = value; // ❌ key="__proto__" pollutes Object.prototype
if (key !== "__proto__" && key !== "constructor" && key !== "prototype")
  obj[key] = value; // ✅
Enter fullscreen mode Exit fullscreen mode

CWE-1321. Caught by secure-coding/detect-object-injection (the rule's own
finding tags CWE-915; CWE-1321 is the canonical JS-prototype-pollution entry).

9. Content Security Policy

An HTTP header that restricts what can load: default-src 'self'; script-src 'self' 'nonce-…'.
CWE-693. browser-security/require-csp-headers flags its absence;
no-unsafe-inline-csp flags the 'unsafe-inline' that defeats it.

10. ReDoS

/^(a+)+$/.test("aaaaaaaaaaaaaaaaaaaaaaaa!"); // ❌ catastrophic backtracking
Enter fullscreen mode Exit fullscreen mode

Regular-Expression Denial of Service. Caught by
secure-coding/no-redos-vulnerable-regex.


Architecture (asked ~40% of the time)

11. Designing secure authentication

  • Password hashing (bcrypt/argon2)
  • Rate limiting on login + account lockout after repeated failures
  • MFA
  • Secure session management
  • Password reset via time-limited tokens

Most of this is architectural, but the enforceable slice is real: the rate-limit
gap on the login route is express-security/require-rate-limiting (CWE-307).

12. Secrets management

Environment variables at minimum; a secrets manager (Vault, AWS Secrets Manager)
in production; nothing in code or git history; a rotation policy. CWE-798
secure-coding/no-hardcoded-credentials is the backstop for the last one.

13. Securing a REST API

AuthN (JWT/OAuth2), AuthZ (RBAC/ABAC), input validation, rate limiting, HTTPS
only, and a tight CORS policy — express-security/require-helmet plus the rate
and CORS rules above cover the configuration half.


Quick-reference: the six with a one-line code fix

Vulnerability Prevention CWE Enforced by
SQL Injection Parameterized queries CWE-89 pg/no-unsafe-query
XSS Output encoding CWE-79 browser-security/no-innerhtml
CSRF Tokens + SameSite CWE-352 express-security/require-csrf-protection
Weak password hash bcrypt / argon2 CWE-916 node-security/no-weak-hash-algorithm
Prototype poll. Key allow-list CWE-1321 secure-coding/detect-object-injection
ReDoS Linear-time regex CWE-1333 secure-coding/no-redos-vulnerable-regex

The "great" answer: enforce it, don't memorize it

Reciting these in an interview proves you know them. Wiring them into CI proves
you'll never ship them. Each concept above maps to a rule in a domain-specific
Interlace plugin — install the layers your
stack uses and the bad version gets flagged (run with --max-warnings 0 in CI so
every finding blocks, not just the error-tier ones):

# npm (yarn/pnpm/bun: same packages, that manager's -D/--dev flag)
npm install --save-dev eslint-plugin-secure-coding eslint-plugin-node-security \
  eslint-plugin-jwt eslint-plugin-pg eslint-plugin-browser-security eslint-plugin-express-security
Enter fullscreen mode Exit fullscreen mode
// eslint.config.mjs — `configs` is a NAMED export (default export is the plugin)
import { configs as secureCoding } from "eslint-plugin-secure-coding";
import { configs as nodeSecurity } from "eslint-plugin-node-security";

export default [secureCoding.recommended, nodeSecurity.recommended];
Enter fullscreen mode Exit fullscreen mode
Surface Support
Package managers npm, yarn, pnpm, bun
Node >= 18.0.0
ESLint `^8.0.0 \
Module system CommonJS — {% raw %}eslint.config.js or .mjs
Oxlint flagship rules wired via the interlace-* ports, CI-gated

For the full OWASP picture (and the two categories static analysis honestly
can't reach), see
the OWASP Top 10 mapping.


Links

⭐ Star on GitHub if you'd rather enforce this list than memorize it for the next interview.


I'm Ofri Peretz, a security engineering leader and the author of the
Interlace ESLint ecosystem — domain-specific static analysis for security,
reliability, and performance on the Node.js stack.

ofriperetz.dev · LinkedIn · GitHub

Top comments (0)