How to Mock a Content Security Policy Header in Python
Mock a Content-Security-Policy header locally and verify it's served correctly using Python's built-in HTTP server.
Python code
36 linesimport json
from http.server import BaseHTTPRequestHandler, HTTPServer
CSP_HEADER = "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'"
class MockServer(BaseHTTPRequestHandler):
def do_GET(self):
if self.path == "/":
self.send_response(200)
self.send_header("Content-Type", "text/html")
self.send_header("Content-Security-Policy", CSP_HEADER)
self.end_headers()
self.wfile.write(b"<html><body><h1>Mock Page</h1></body></html>")
else:
self.send_response(404)
self.end_headers()
def log_message(self, format, *args):
pass
if __name__ == "__main__":
server = HTTPServer(("localhost", 8000), MockServer)
headers = {
"Content-Security-Policy": CSP_HEADER
}
print("Mock server starting on port 8000")
print(f"CSP header being served: {headers['Content-Security-Policy']}")
print("Startup verification: sending test request...")
import urllib.request
with urllib.request.urlopen("http://localhost:8000/") as response:
received_header = response.headers.get("Content-Security-Policy")
print(f"Received CSP header: {received_header}")
print(f"CSP header match: {received_header == CSP_HEADER}")
server.shutdown() # Clean shutdown after verification
Output
Mock server starting on port 8000
CSP header being served: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'
Startup verification: sending test request...
Received CSP header: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'
CSP header match: True
How it works
The BaseHTTPRequestHandler handles incoming GET requests by sending the CSP header in do_GET. Using the standard library's http.server, we build a lightweight mock that doesn't require external dependencies. The send_header method adds the Content-Security-Policy header to the response. A urllib.request request is made during startup to verify the header is served correctly. log_message is overridden to suppress default logging, keeping output clean.
This pattern lets you test browser behavior against CSP policies in local development or CI without a full server stack.
Common mistakes
- Sending the CSP header after `end_headers()` — must be called before it
- Forgetting to set `Content-Type` header alongside CSP for valid HTML responses
- Hardcoding mismatched CSP values between test and production configs
Variations
- Use Flask's `@app.after_request` to add the header to every response in a dev app
- Read the CSP policy from an environment variable or config file instead of a constant
Real-world use cases
- Testing a browser extension or SPA locally against a specific CSP policy during development.
- Simulating a backend endpoint that serves CSP headers for integration tests in CI pipelines.
- Debugging mixed content or inline script errors by reproducing the exact policy in a mock server.
Sponsored
More from Auth & security at scale
- ACME LetsEncrypt Mock Challenge Server in Python medium
- AES GCM encryption and decryption in Python medium
- Build a Mock OIDC Userinfo Endpoint in Python with Flask easy
- ChaCha20-Poly1305 mock in Python medium
- ECDH key agreement in Python with cryptography medium
- Enforce TLS 1.2 Minimum in Python easy
Keep learning
Related tutorials and quizzes for this topic.