Understanding Content Security Policy (CSP): Implementing Secure Headers
Learn how to configure a Content Security Policy (CSP) header, use hash and nonce attributes, and protect your web applications from Cross-Site Scripting (XSS).
Understanding Content Security Policy (CSP): Implementing Secure Headers
Cross-Site Scripting (XSS) and data injection attacks remain some of the most common security vulnerabilities on the web. While validating user input is essential, the browser needs a fallback security layer to restrict where scripts and resources can be loaded from. This layer is the Content Security Policy (CSP).
In this guide, we'll outline how CSP works, dissect key directives, and implement nonce-based script execution.
🔒 What is Content Security Policy?
Content Security Policy is an HTTP response header that tells the browser which dynamic resources are authorized to load and execute. If a malicious script is injected into your HTML page, the browser will refuse to run it if the script's origin does not match the CSP directives.
The header name is:
Content-Security-Policy: <directive> <source-list>; <directive> <source-list>;
🚦 Core CSP Directives and Scope
A robust policy defines restrictions for multiple resource types:
default-src: The fallback policy for resource types that do not have an explicit directive defined.script-src: Restricts the origins of executable JavaScript files and inline scripts.img-src: Declares valid sources of images.style-src: Controls where stylesheets can be loaded from.connect-src: Limits the targets of AJAX calls, WebSocket connections, and Fetch APIs.
🛠️ Hash vs. Nonce: Securing Inline Scripts
[!WARNING] By default, strict CSP configurations block all inline scripts (e.g.
<script>console.log('hi');</script>) to prevent XSS. To run inline scripts securely, you must use a nonce or a hash.
1. Nonce-Based Verification (Recommended)
A nonce is a cryptographically strong, random token generated by the server on every single request.
1. The server generates a nonce: nonce = "EDNnf03nceIurj33sD".
2. The server injects this nonce into the HTTP response header:
Content-Security-Policy: script-src 'self' 'nonce-EDNnf03nceIurj33sD';
3. The server attaches the nonce attribute to authorized inline scripts:
html
<script nonce="EDNnf03nceIurj33sD">
// This script will run successfully
console.log("Secure script execution");
</script>
An attacker cannot execute injected scripts because they cannot guess the random nonce value generated for that specific request.
2. Hash-Based Verification
Useful for static inline scripts that do not change. You generate a SHA-256 hash of the script's exact contents and add it to the CSP header:
script-src 'self' 'sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=';
💻 Sample CSP Configuration in Python (Flask)
Here is how to set up a secure Content Security Policy header in a Flask backend application:
```python from flask import Flask, make_response import secrets
app = Flask(name)
@app.route('/') def home(): # 1. Generate a secure, request-unique random nonce nonce = secrets.token_urlsafe(16)
# 2. Render response
response = make_response(render_template('index.html', nonce=nonce))
# 3. Apply strict CSP headers
csp = (
f"default-src 'self'; "
f"script-src 'self' 'nonce-{nonce}'; "
f"style-src 'self' https://fonts.googleapis.com; "
f"img-src 'self' data:; "
f"connect-src 'self';"
)
response.headers['Content-Security-Policy'] = csp
return response
```
Join the Urbandigistore Hub
Subscribe to receive premium developer cheat sheets, advanced conversion techniques, and campaign optimization checklists. Zero spam, unsubscribe anytime.