Implementing Strict Content Security Policy ( CSP ) in Vue.js & Django with Nginx
Increase the security of your Vue.js app with CSP

Hi, I’m a self-taught backend developer with 3+ years of experience, currently working at a tech startup based in The Bahamas. I mostly work with Python and Django, building APIs, designing database models, and improving performance when needed. I enjoy learning new tools and technologies as projects require.
Introduction
Content Security Policy (CSP) is a security standard that helps prevent cross-site scripting (XSS), clickjacking, and other code-injection attacks by whitelisting trusted sources of content. When correctly configured, CSP ensures that only approved scripts, styles, images, and connections can be loaded by the browser.
Why CSP Matters
Without a strict CSP, an attacker could inject malicious scripts into your application, steal user credentials, or redirect users to phishing pages:
How CSP Works
When the browser receives HTML along with a CSP header, it enforces each directive on every resource request:
Browser Enforcement Flow
This diagram shows how the browser enforces CSP on resources like scripts, styles, images, and XHR/fetch requests:
Configuring CSP in Nginx for Vue.js
In your Nginx server block for the Vue.js static build, add a CSP header:
server {
listen 80;
server_name yourdomain.com;
root /var/www/vue-dist;
index index.html;
add_header Content-Security-Policy "
default-src 'self';
script-src 'self' https://cdn.jsdelivr.net;
style-src 'self' 'unsafe-inline';
img-src 'self' data:;
font-src 'self' https://fonts.gstatic.com;
connect-src 'self' https://api.yourdomain.com;
" always;
location / {
try_files $uri $uri/ /index.html;
}
}
- default-src: Fallback for all resource types.
- script-src: Whitelist your own bundle and trusted CDNs.
- style-src: Allow inline styles for runtime libraries like Floating-UI.
- img-src: Permit data URIs for base64 images.
- font-src: Load web fonts from trusted providers.
- connect-src: Ensure the SPA can communicate with the Django API.
Configuring CSP in Django
Use the django-csp middleware or a custom header:
Using django-csp
# settings.py
MIDDLEWARE = [
# ...
'csp.middleware.CSPMiddleware',
]
CSP_DEFAULT_SRC = ("'self'",)
CSP_SCRIPT_SRC = ("'self'", "https://cdn.jsdelivr.net")
CSP_STYLE_SRC = ("'self'", "'unsafe-inline'")
CSP_IMG_SRC = ("'self'", "data:")
CSP_CONNECT_SRC = ("'self'", "https://api.yourdomain.com")
Custom Middleware
# middleware.py
from django.utils.deprecation import MiddlewareMixin
class ContentSecurityPolicyMiddleware(MiddlewareMixin):
def process_response(self, request, response):
policy = (
"default-src 'self'; "
"script-src 'self' https://cdn.jsdelivr.net; "
"style-src 'self' 'unsafe-inline'; "
"img-src 'self' data:; "
"connect-src 'self' https://api.yourdomain.com;"
)
response['Content-Security-Policy'] = policy
return response
Note: If your Django project only serves API endpoints (no HTML responses or templates), you typically don't need to configure CSP on the Django side. Simply enforce CSP at your Nginx or frontend layer.
Inline Script Handling
When an attacker tries to inject inline <script> tags via URL parameters or form inputs, CSP will block execution:
Testing & Troubleshooting
- Check the browser console for “Refused to load” errors.
- Whitelisting: Add missing domains in the right directive (e.g.,
connect-srcvs.script-src). - Certificate permissions: Ensure Nginx can read SSL cert files if using HTTPS.
- Disable Rocket Loader (Cloudflare) if you must avoid
'unsafe-inline'for scripts.
Conclusion
Implementing a strict Content Security Policy via Nginx and Django dramatically reduces the risk of XSS and resource injection attacks. By carefully whitelisting only trusted sources and monitoring violations, you harden both your Vue.js frontend and Django backend against a wide range of threats.






