Swipe left or right to navigate to next or previous post

Content Security Policy (CSP) in Django App

27 Nov 2024 . category: Programming . Comments
#Programming #Security #Django #Backend

Content Security Policy (CSP) in Django - A Shield Against Modern Web Vulnerabilities - Tapan BK

A Content Security Policy (CSP) is an effective security measure that helps protect Django applications from Cross-Site Scripting (XSS) attacks and other code injection threats. By defining CSP rules, you control how and where your application’s resources are loaded or executed.

Why Use CSP in Django?

Django applications often involve user-generated content or depend on external scripts and libraries, making them potential targets for XSS attacks. With CSP, you can:

  • Restrict the sources of scripts, styles, and other resources.
  • Block unauthorized inline scripts or styles.
  • Disable dangerous functionalities like eval().

Setting Up CSP in Django

Django does not include native CSP support, but you can implement CSP policies using middleware or third-party packages.

Using Django-CSP Package

Django-CSP is a popular package that integrates CSP into your Django project. Follow these steps:

  1. Install the package:
    pip install django-csp
  2. Add Middleware: Include django_csp.middleware.CSPMiddleware in your MIDDLEWARE setting.
    
    MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'csp.middleware.CSPMiddleware',
    # other middleware
    ]
    
  3. Define CSP Policies: Set CSP directives in your settings.py.
    
    # These are just the examples
    CSP_DEFAULT_SRC="'self'"
    CSP_SCRIPT_SRC="'self','strict-dynamic','unsafe-inline',unpkg.com,npmcdn.com,ajax.googleapis.com,cdnjs.cloudflare.com"
    CSP_SCRIPT_SRC_ELEM="'self',unpkg.com,npmcdn.com,ajax.googleapis.com,cdnjs.cloudflare.com"
    CSP_STYLE_SRC="'self',cdnjs.cloudflare.com"
    CSP_STYLE_SRC_ELEM="'self',cdnjs.cloudflare.com"
    CSP_FONT_SRC="'self',fonts.googleapis.com"
    CSP_IMG_SRC="'self',data:"
    CSP_FRAME_SRC="'self'"
    CSP_BASE_URI="'self'"
    CSP_REQUIRE_TRUSTED_TYPES_FOR=""
    

Using Custom Middleware

If you prefer not to use a third-party package, you can implement CSP using custom middleware.

  1. Create Middleware:
    
    class ContentSecurityPolicyMiddleware:
            def process_request(self, request):
                if not hasattr(request, 'csp_nonce'):
                    request.csp_nonce = uuid.uuid4().hex
            
            def process_response(self, request, response):
                nonce = getattr(request, 'csp_nonce', None)
                if nonce:
                    csp_directives = {
                        'default-src': settings.CSP_DEFAULT_SRC,
                        'script-src': settings.CSP_SCRIPT_SRC,
                        'script-src-elem': settings.CSP_SCRIPT_SRC_ELEM,
                        'style-src': settings.CSP_STYLE_SRC,
                        'style-src-elem': settings.CSP_STYLE_SRC_ELEM,
                        'font-src': settings.CSP_FONT_SRC,
                        'img-src': settings.CSP_IMG_SRC,
                        'frame-src': settings.CSP_FRAME_SRC,
                        'base-uri': settings.CSP_BASE_URI,
                        'require-trusted-types-for': settings.CSP_REQUIRE_TRUSTED_TYPES_FOR,
                    }
                    for directive in ['script-src', 'script-src-elem',  'style-src', 'style-src-elem']:
                        if csp_directives.get(directive):
                            csp_directives[directive] = list(csp_directives[directive]) + [f"'nonce-{nonce}'"]
            
                    csp_header = '; '.join(
                        f"{directive} {' '.join(sources)}" for directive, sources in csp_directives.items() if sources)
                    response['Content-Security-Policy'] = csp_header
                return response
     
  2. Add Middleware: Include it in your settings.py.
    
    MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'yourapp.csp_middleware.ContentSecurityPolicyMiddleware',
    # other middleware
    ]
    

Handling Inline Scripts and Styles using nonce from middleware

CSP blocks inline scripts and styles by default. Use nonces or hashes to allow specific inline content. The nonce are generated from above middleware and used in every templates files by `request.csp_nonce`

Use Nonce in Templates: Add the nonce to your inline scripts and styles.

<script nonce="{{ request.csp_nonce }}">
console.log('This script is allowed by CSP.');
</script>

Handling Inline Scripts and Styles by adding nonce value in response

  1. Generate a Nonce: Create a unique token for every page load.
    
    from django.utils.crypto import get_random_string
    def add_nonce_to_context(request):
        nonce = get_random_string(16)
        request.csp_nonce = nonce
        return nonce
    
  2. Set CSP Header with Nonce for response of the request:
    
    response["Content-Security-Policy"] = f"script-src 'self' 'nonce-{nonce}';"
    
  3. And finally use Nonce in Templates
    
    <script nonce="{{ request.csp_nonce }}">
    console.log('This script is allowed by CSP.');
    </script>
    

Using Hashes in CSP (Content Security Policy)

You can also allow specific inline scripts by calculating and including a hash of their content in the CSP header.


Content-Security-Policy: script-src 'self' 'sha256-xyz123...';

Reporting CSP Violations

Enable CSP violation reporting to monitor and fine-tune your policies.


CSP_REPORT_URI = "https://your-server.com/csp-violation-report"
CSP_REPORT_ONLY = True  # Test policies without enforcing them

Create an endpoint to handle violation reports and log them for analysis.

Best Practices

  • Start with Report-Only Mode: Test your policies without enforcement to identify potential issues.
  • Whitelist Trusted Sources: Allow resources only from domains you trust.
  • Audit Regularly: Review and update your CSP as your application evolves.

Implementing CSP in Django enhances your application's security and provides protection against common vulnerabilities.

Want to Explore more on Content security policy - A Shield Against Modern Web Vulnerabilities, Please visit

  1. Content Security Policy overview
  2. Content Security Policy in inline styles and scripts
  3. Content Security Policy using Hash methods

Tapan B.K. | Full Stack Software Engineer

Tapan B.K. is Full Stack Software Engineer. In his spare time, Tapan likes to watch movies, visit new places.