New: We've launched a brand new Coding Challenges section! Check out these interactive, real-world exercises to level up your skills.Explore Challenges
FrontendPrep
securityHard

Web Security: Content Security Policy (CSP) in Depth

Loading...

Master Content Security Policy (CSP). Learn how to declare strict CSP directives, use nonces and hashes, restrict object/script sources, and set up violation report logging.

Arvind M
Arvind MLinkedIn

Web Security: Content Security Policy (CSP) in Depth

One of the most frequent advanced security questions in frontend interviews is:

What is Content Security Policy (CSP)? How do you build a strict CSP directive, and how do nonces and hashes protect against Cross-Site Scripting (XSS)?

Content Security Policy (CSP) is an HTTP response header that defines which resources (scripts, stylesheets, images, connections) the browser is allowed to load and execute for a specific webpage. It acts as a powerful layer of defense to mitigate Cross-Site Scripting (XSS) and data injection attacks.


1. Declarative CSP Directives

The Content-Security-Policy header contains a semi-colon separated list of directives:

Content-Security-Policy: default-src 'self'; script-src 'self' https://trustedscripts.com; img-src 'self' data:;

Core Directives:

  • default-src: Fallback policy for other resource fetch directives when they are not explicitly specified.
  • script-src: Restricts the origins that can execute JavaScript on the page.
  • style-src: Restricts CSS source origins.
  • img-src: Restricts image source origins.
  • connect-src: Restricts the target URLs that client-side JavaScript can request (using fetch, XMLHttpRequest, or WebSockets).
  • frame-ancestors: Restricts which sites can embed this page inside an <iframe>, preventing Clickjacking attacks.

2. Eliminating 'unsafe-inline' with Nonces and Hashes

By default, strict CSP configurations block inline scripts:

<script>runMaliciousCode();</script> <!-- Blocked by strict CSP! -->

Historically, developers resolved this by adding 'unsafe-inline' to the script-src directive, which completely defeats the anti-XSS benefits of CSP. Instead, you should use:

A. Nonces (Number used once)

A nonce is a cryptographically strong, randomly generated token generated by the server on every single page request:

  1. The server generates a unique token (e.g. d392a83f982) and adds it to the HTTP CSP header:
    Content-Security-Policy: script-src 'self' 'nonce-d392a83f982';
  2. The server injects the matching attribute to valid inline script tags in the HTML document:
    <script nonce="d392a83f982">console.log("Safe script run!");</script>

If an attacker injects a script tag without the correct matching nonce token, the browser blocks execution.

B. Hashes

If you have static inline scripts that do not change, you can compute their SHA-256 hash and declare the hash signature inside the CSP header:

  1. Compute the hash of the exact script content: console.log("Hello"); -> sha256-R43...
  2. Define the hash in the CSP header:
    Content-Security-Policy: script-src 'self' 'sha256-R43uF5...';

3. CSP Violation Reporting

You can monitor policy violations in production without blocking resources by using the Content-Security-Policy-Report-Only header combined with a report URI destination:

Content-Security-Policy-Report-Only: default-src 'self'; report-uri https://api.my-app.com/csp-report;

The browser will send a JSON payload to the report-uri whenever a policy restriction is violated, helping you identify and fix bugs before enforcing strict blocking.


Key Takeaways

  • Strict Fallbacks: Always set a restrictive default-src 'self' fallback policy.
  • Avoid Unsafe Keywords: Never use 'unsafe-inline' or 'unsafe-eval' in production stylesheets or scripts unless absolutely necessary.
  • Dynamic Nonces: Generate unique nonces per request on server rendering passes; do not use static reusable nonces.
  • Report-Only for Staging: Use the Report-Only header to validate CSP configs before fully rolling out blocking headers.

Finished practicing this challenge?

Mark it as completed to track your progress, or bookmark it to review later.

Loading...

Share this Resource

Help other developers level up by sharing this study guide.

⚡ Weekly newsletter

Crack Your Next Frontend Interview.

Join senior engineers who receive practical, deep-dive frontend challenges, detailed concepts, and blueprints directly in their inbox.

  • Senior level React, JS, and CSS interview blueprints
  • System Design & performance optimization deep-dives
  • 100% free, zero spam, unsubscribe with one click

Join the Study Track

We value your privacy. Unsubscribe at any time.

More Technical Questions

Expand your mastery. Deep dive into other frontend interview challenges in this category.