System-design · Frontend Security

Frontend Security Interview Questions
With Answers & Code Examples

6 carefully curated Frontend Security interview questions with working code examples and real interview gotchas.

Practice Interactively →← All Categories
6 questions3 beginner2 core1 advanced
Q1Beginner

What is XSS (Cross-Site Scripting) and how do you prevent it?

💡 Hint: Attacker injects script that runs in another user's browser — prevent by escaping output, using CSP, and never using innerHTML with user data

XSS occurs when an attacker injects malicious JavaScript into a page that is then executed in another user's browser, giving the attacker access to cookies, tokens, and the DOM.

Three types:

  • Stored XSS — malicious script is saved in the database (e.g., a comment) and served to every user who views it.
  • Reflected XSS — script is embedded in a URL, reflected in the response (e.g., search results page).
  • DOM-based XSS — client-side JS reads attacker-controlled data (URL hash, postMessage) and writes it to the DOM unsafely.

Prevention:

  • Never use innerHTML, dangerouslySetInnerHTML, or document.write with untrusted data. React auto-escapes by default — this is why it's safer.
  • Output encoding — HTML-encode user content before rendering it.
  • Content Security Policy (CSP) — restricts which scripts can execute; blocks inline scripts.
  • Sanitize HTML input — if you must allow rich text, use DOMPurify.
import DOMPurify from 'dompurify';
// Safe: sanitize before dangerouslySetInnerHTML
const clean = DOMPurify.sanitize(userHtml);
<div dangerouslySetInnerHTML={{ __html: clean }} />
Practice this question →
Q2Beginner

What is CSRF and how do SameSite cookies and CSRF tokens prevent it?

💡 Hint: Forged cross-origin request that rides on the victim's cookies — SameSite blocks cookie sending; CSRF token requires secret the attacker doesn't have

CSRF (Cross-Site Request Forgery) tricks a logged-in user's browser into making an unintended request to a site where they're authenticated. The browser automatically sends cookies, so the server sees it as legitimate.

<!-- On attacker's site -->
<img src="https://bank.com/transfer?to=attacker&amount=1000" />
<!-- Browser auto-sends bank.com cookies with this request -->

Prevention 1: SameSite cookies

  • SameSite=Strict — cookie never sent on cross-origin requests. Breaks OAuth flows.
  • SameSite=Lax — cookie sent on top-level navigations (GET links) but not on embedded requests (img, form POST from other sites). Good default.
  • SameSite=None; Secure — sent everywhere (cross-origin). Requires HTTPS.

Prevention 2: CSRF tokens

// Server sets a CSRF token in a readable cookie (not HttpOnly) or in page HTML
// Client reads it and sends it as a header
const csrfToken = getCookieValue('csrf-token');
fetch('/api/transfer', {
  method: 'POST',
  headers: { 'X-CSRF-Token': csrfToken }, // attacker can't read this
});

Attackers can't read the CSRF token from a different origin (same-origin policy), so they can't forge the header.

Practice this question →
Q3Core

What is a Content Security Policy (CSP) and how does it work?

💡 Hint: HTTP header that whitelists sources for scripts, styles, images — blocks injected inline scripts and unknown CDNs

A Content Security Policy is an HTTP response header that tells the browser which sources are allowed to load scripts, styles, images, fonts, etc. Violations are blocked.

Content-Security-Policy:
  default-src 'self';
  script-src 'self' https://cdn.example.com;
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: https:;
  frame-ancestors 'none';

Key directives:

  • default-src — fallback for all resource types not explicitly listed.
  • script-src — which origins can serve JavaScript.
  • frame-ancestors — which origins can embed this page in an iframe (replaces X-Frame-Options).
  • 'nonce-{random}' — whitelist an inline script by including a per-request nonce: <script nonce="r4nd0m">.
  • 'strict-dynamic' — trust scripts loaded by trusted scripts (allows dynamic script injection from whitelisted scripts).

Reporting: Use Content-Security-Policy-Report-Only header to log violations without blocking — essential when rolling out a CSP to a production app.

💡 Aim for a CSP that eliminates 'unsafe-inline' for scripts. Nonces (Next.js middleware) are the practical way to achieve this with SSR apps.
Practice this question →
Q4Beginner

What is clickjacking and how do you prevent it?

💡 Hint: Attacker overlays your page in a transparent iframe — victim clicks on attacker UI but triggers your authenticated actions; prevent with frame-ancestors CSP

Clickjacking is an attack where a malicious page embeds your site in a transparent <iframe>. The victim sees the attacker's UI but their clicks land on your page's controls (like a "Transfer Funds" button).

Prevention methods:

1. Content-Security-Policy: frame-ancestors (preferred)

Content-Security-Policy: frame-ancestors 'none';
// or allow only same origin:
Content-Security-Policy: frame-ancestors 'self';

2. X-Frame-Options (legacy, still supported)

X-Frame-Options: DENY
X-Frame-Options: SAMEORIGIN

frame-ancestors in CSP supersedes X-Frame-Options and supports more granular control (e.g., allow specific partners).

3. Frame-busting JS (weak, not recommended)

if (window.top !== window.self) window.top.location = window.location;

Attackers can defeat this with sandbox attribute on the iframe. Always use HTTP headers instead.

Practice this question →
Q5Core

What security HTTP response headers should every production frontend set?

💡 Hint: X-Content-Type-Options, X-Frame-Options/CSP frame-ancestors, HSTS, Referrer-Policy, Permissions-Policy

A hardened production app should set these headers on every HTML response:

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
# Forces HTTPS for 1 year; prevents SSL-stripping attacks

X-Content-Type-Options: nosniff
# Stops browser MIME-type sniffing — prevents treating a text/plain response as JavaScript

X-Frame-Options: DENY
Content-Security-Policy: frame-ancestors 'none'
# Prevents clickjacking

Referrer-Policy: strict-origin-when-cross-origin
# Limits how much URL info leaks in Referer header

Permissions-Policy: camera=(), microphone=(), geolocation=()
# Disables browser features your app doesn't use

Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{n}'; ...
# Restricts resource origins; mitigates XSS

Quick audit: Run your URL through securityheaders.com to get a score and missing header report.

In Next.js: Set these in next.config.js under headers() or in middleware for per-request nonces.

Practice this question →
Q6Advanced

How do you protect a frontend app against dependency supply chain attacks?

💡 Hint: Lock file, Subresource Integrity, audit CI, minimal dependencies, private registry proxying

Supply chain attacks target the npm packages your app depends on (e.g., the event-stream malware, left-pad removal, typosquatting).

Defenses:

1. Lock files — commit package-lock.json or pnpm-lock.yaml. CI runs npm ci (not npm install) to install exact locked versions.

2. Automated auditing — run npm audit or pnpm audit in CI; fail the build on high-severity CVEs. Dependabot or Renovate auto-opens PRs for patches.

3. Subresource Integrity (SRI) — for third-party CDN scripts, add a integrity hash. Browser refuses to execute the script if the hash doesn't match.

<script
  src="https://cdn.example.com/lib.js"
  integrity="sha384-abc123..."
  crossorigin="anonymous"></script>

4. Minimal dependency footprint — every added package is an attack surface. Prefer native browser APIs; audit new deps on Bundlephobia and Snyk before adding them.

5. Private registry proxy — proxy npm through Artifactory or Verdaccio; allows allow-listing, caching, and scanning before packages reach developers.

Practice this question →

Other System-design Interview Topics

Rendering StrategiesCore JSType SystemReact FundamentalsFunctionsMicrofrontendsGenericsAsync JSHooksObjectsMonorepoArrays'this' KeywordUtility TypesError HandlingModern JSBundle OptimizationPerformanceDOM & EventsState ManagementClasses & OOPCaching StrategiesComponent PatternsAdvanced TypesAuthenticationReact RouterFormsAdvanced PatternsConcurrent ReactServer ComponentsTestingEcosystemNetwork OptimizationCore Web VitalsBrowser APIs

Ready to practice Frontend Security?

Get AI feedback on your answers, predict code output, and fix real bugs.

Start Free Practice →