Giter VIP home page Giter VIP logo

Comments (3)

some1ataplace avatar some1ataplace commented on July 28, 2024 2

To exclude nonces from the default-src when CSP_INCLUDE_NONCE_IN is unset or an empty list, we need to modify the CSPMiddleware class of django-csp.

We can modify the _build_policy method of the CSPMiddleware class to conditionally include nonces in the default-src directive based on whether CSP_INCLUDE_NONCE_IN is set. If it is, we include the nonce in the specified directive, and if not, we exclude it.

Here is an updated version of the _build_policy method that implements this behavior:

def _build_policy(self, nonce=None):
    cspsettings = {key[len('CSP'):]: value for key, value in getattr(settings, 'CSP_CONFIG', {}).items()}
    policy = {}

    # Add directives that aren't on by default
    for directive in self.directives:
        if directive in csp_settings:
            policy[directive] = csp_settings[directive]

    # Add directives that are on by default
    for directive in self.default_on_directives:
        # Check whether we should include nonces in this directive
        if 'CSP_INCLUDE_NONCE_IN' in getattr(settings, 'CSP_CONFIG', {}):
            include_nonce = self.directive_matches(directive, getattr(settings, 'CSP_CONFIG', {})['CSP_INCLUDE_NONCE_IN'])

        if directive not in policy:
            # By default, the following default-src is always set
            if directive == 'default-src':
                if include_nonce:
                    policy[directive] = "'self' 'unsafe-inline' 'unsafe-eval'; base-uri 'self'; form-action 'self'"
                else:
                    policy[directive] = "'self' 'unsafe-inline' 'unsafe-eval'; base-uri 'self'; form-action 'self';nonce-{0}".format(nonce)
            else:
                # Append nonce to other directives that support it
                if include_nonce:
                    policy[directive] = "'self' 'unsafe-inline' 'unsafe-eval'; base-uri 'self'; form-action 'self';nonce-{0}".format(nonce)
                else:
                    policy[directive] = "'self' 'unsafe-inline' 'unsafe-eval'; base-uri 'self'; form-action 'self'"

    for directive in self.default_src_directives:
        # Check whether we should include nonces in this directive
        if 'CSP_INCLUDE_NONCE_IN' in getattr(settings, 'CSP_CONFIG', {}):
            include_nonce = self.directive_matches(directive, getattr(settings, 'CSP_CONFIG', {})['CSP_INCLUDE_NONCE_IN'])

        # Only include 'self' directive in default-src if not including a nonce in it
        if directive == 'self' and not include_nonce:
            continue

        # Append nonce to default-src if including nonces in it
        if include_nonce:
            policy['default-src'] += " 'nonce-{0}'".format(nonce)
        else:
            policy['default-src'] += " '{0}'".format(directive)

    return policy
from django.test import RequestFactory, TestCase
from django.http import HttpResponse
from django.urls import reverse
from django_csp.middleware import CSPMiddleware
from myapp.views import MyView

class CSPMiddlewareTest(TestCase):
    def setUp(self):
        self.factory = RequestFactory()

    def test_process_request_with_CSP(self):
        # Create a request object and a response object
        request = self.factory.get('/my-view/')
        response = HttpResponse()

        # Create a middleware object and call the process_request method
        middleware = CSPMiddleware(get_response=None)
        result = middleware.process_request(request)

        # Verify that the process_request method returns None since the response object does not have a CSP header yet
        self.assertIsNone(result)

        # Call the process_response method and verify that the response object now has a CSP header
        middleware.process_response(request, response)
        self.assertTrue('Content-Security-Policy' in response)

    def test_process_request_exempt_from_CSP(self):
        # Create a request object that should be exempt from CSP
        request = self.factory.get('/my-view/')

        # Create a response object with the CSP header
        response = HttpResponse()
        middleware = CSPMiddleware(get_response=None)
        response['Content-Security-Policy'] = middleware._build_policy({})

        # Set the exempt_urls attribute to include the URL path of the request object
        middleware.exempt_urls = ['/my-view/']

        # Verify that the process_request method returns None since the URL path of the request is exempt from CSP
        self.assertIsNone(middleware.process_request(request))

    def test_process_response_with_CSP_decorator(self):
        # Create a request object and a response object
        request = self.factory.get(reverse('my-view'))

To modify django-csp to exclude nonces from default-src when CSP_INCLUDE_NONCE_IN is unset or an empty list, you can modify the get_nonce_included_directives function in csp/utils.py as follows:

def get_nonce_included_directives(include_nonce_in):
    """
    Returns a list of directives that should include nonces.
    """
    if not include_nonce_in:
        return []
    if include_nonce_in == ['default-src']:
        return ['default-src']
    return include_nonce_in + ['default-src']

This modified function checks if include_nonce_in is unset or an empty list, and returns an empty list if so. Otherwise, it returns include_nonce_in plus 'default-src', which excludes the nonce from the default-src directive.


from django.test import TestCase

from mozilla.django_csp.utils import get_nonce_included_directives

class GetNonceIncludedDirectivesTestCase(TestCase):
    """
    Test case for the get_nonce_included_directives() utility function.
    """

    def test_empty_include_nonce_in(self):
        """
        Test for when include_nonce_in is an empty list.
        """
        result = get_nonce_included_directives([])
        self.assertEqual(result, [])

    def test_default_src_included(self):
        """
        Test for when include_nonce_in is ['default-src'].
        """
        result = get_nonce_included_directives(['default-src'])
        self.assertEqual(result, ['default-src'])

    def test_other_directives_included(self):
        """
        Test for when include_nonce_in contains other directives besides 'default-src'.
        """
        result = get_nonce_included_directives(['script-src', 'style-src'])
        self.assertEqual(result, ['script-src', 'style-src', 'default-src'])

    def test_none_include_nonce_in(self):
        """
        Test for when include_nonce_in is None.
        """
        result = get_nonce_included_directives(None)
        self.assertEqual(result, ['default-src'])

from django-csp.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.