This Python script analyzes a website and generates a Content Security Policy (CSP) header with an optional reporting mechanism. It's designed to help website administrators create an initial CSP for their site.
-
Ensure you have Python 3.6 or later installed.
-
Clone this repository or download the script files.
-
Install the required dependencies:
python3 -m venv venv # Activate the venv on macOS/Linux: source /venv/bin/activate # Activate the venv on Windows: venv\Scripts\activate pip install -r requirements.txt
Run the script from the command line, providing the URL of the page you want to analyze:
python csp_generator.py https://www.example.com/foo
To enable CSP violation reporting, add the --report-uri argument:
python csp_generator.py https://www.example.com/foo --report-uri https://your-reporting-endpoint.com/csp-report
For the most comprehensive CSP, you should run the script on multiple pages of your website, especially:
- The homepage
- Key landing pages
- Pages with unique functionality or third-party integrations
- Pages with user-generated content
After analyzing multiple pages, combine the results to create a CSP that covers all necessary resources across your site.
The script will generate:
- A Content Security Policy header
- A nonce for inline scripts (note: this is static in the current implementation)
- If enabled, information about CSP violation reporting
- The generated CSP is a starting point and should be thoroughly tested before deployment.
- The nonce generated is static and should not be used as-is in a production environment (see the "Security Considerations" section below).
- Regular updates to the CSP may be necessary as your website evolves.
The CSP generated by this script has several limitations:
- Static Nonce: The script generates a single, static nonce. In a secure implementation, nonces should be dynamically generated for each page load.
- Lack of Real-time Updates: A static CSP can't adapt to dynamic content or new resources added to your site without manual updates.
- Potential for Over-permissiveness: To avoid breaking functionality, a static CSP might be overly permissive, potentially reducing its security benefits.
- Maintenance Burden: Regular manual updates are required to keep the CSP in sync with website changes.
For a more secure implementation, you should integrate dynamic nonce generation into your web application. Here's a general approach:
-
Server-side Nonce Generation: Generate a new, random nonce for each page request.
-
Inject Nonce into CSP Header: Modify your server configuration or application code to include the generated nonce in the CSP header.
-
Add Nonce to Inline Scripts: Inject the same nonce into the
nonceattribute of all inline<script>tags in your HTML.
from flask import Flask, render_template, make_response
import secrets
app = Flask(__name__)
@app.route('/')
def home():
nonce = secrets.token_urlsafe(16)
csp = f"default-src 'self'; script-src 'self' 'nonce-{nonce}' 'strict-dynamic';"
response = make_response(render_template('home.html', nonce=nonce))
response.headers['Content-Security-Policy'] = csp
return responseIn your HTML template:
<script nonce="{{ nonce }}">
// Your inline JavaScript here
</script>To use the script-generated CSP with dynamic nonces:
-
Run the script to generate a base CSP.
-
In your web application, implement dynamic nonce generation as shown above.
-
Modify the script-generated CSP to use a placeholder for the nonce:
Content-Security-Policy: script-src 'nonce-{NONCE}' 'strict-dynamic' https: ... -
In your application code, replace
{NONCE}with the dynamically generated nonce for each request.
Remember, while this script is a useful tool for creating an initial CSP, a robust security strategy involves continuous monitoring, testing, and updating of your security policies.