Giter VIP home page Giter VIP logo

Comments (1)

some1ataplace avatar some1ataplace commented on July 28, 2024
from csp.utils import build_policy, get_nonce_generator

def custom_build_policy(
        policies, overrides=None, nonce_generator=get_nonce_generator(),
        report_only=False):
    # Include your custom logic here to manipulate policies and overrides as desired

    csp = build_policy(policies, overrides=overrides, report_only=report_only)
    return csp

def construct_final_string(policy_parts):
    # Include your custom logic here to construct the final string
    # based on policy_parts

    final = "; ".join(policy_parts)
    final = " ".join([final, "report-uri /csp_reports/"])
    return final

def add_nonce(policy, source):
    # Include logic here to add a nonce to the specified source if necessary
    return source

# Update the original build_policy function to call the new functions
def build_policy(policies, overrides=None, nonce_generator=get_nonce_generator(),
                 report_only=False):
    policy_parts = []
    for policy in policies:
        for name, value in policy.items():
            # Handle the nonce directive here
            if name == 'nonce':
                continue
            elif name in ('default-src', 'script-src', 'style-src', 'img-src', 'connect-src', 
                 'font-src','media-src', 'object-src', 'child-src', 'frame-src', 'worker-src',
                 'manifest-src', 'base-uri', 'form-action', 'frame-ancestors',
                 'plugin-types', 'sandbox', 'navigate-to', 'block-all-mixed-content',
                 'upgrade-insecure-requests', 'require-sri-for'):
                # Split multiple directives where necessary
                values = [v.strip() for v in value.split(';') if v.strip()]

                # Add nonces to sources if necessary
                if nonce_generator and name in ('script-src', 'style-src', 'default-src'):
                    values = [add_nonce(policy, v) if 'nonce' not in v else v for v in values]

                # Append the directive with its values
                policy_parts.append(' '.join([name] + values))

    final = construct_final_string(policy_parts)
    return final

The custom_build_policy function takes a list of policy dictionaries and some optional arguments, and returns a CSP header string. The build_policy function is called by custom_build_policy and constructs the policy header by iterating over the policy dictionaries and their key-value pairs.

The construct_final_string function takes a list of policy strings and constructs the final CSP header string by joining them together with semicolons and adding a report URI.

The add_nonce function is called by build_policy for certain policy types and adds a nonce value to the allowed sources to prevent script injection attacks.

from django.test import TestCase, RequestFactory
from django.http import HttpResponse
from django.urls import reverse
from django_csp.middleware import CSPMiddleware

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

    def test_can_process_request(self):
        request = self.factory.get(reverse('home'))
        middleware = CSPMiddleware(None)
        response = middleware.process_request(request)
        self.assertIsNone(response)

    def test_can_pre_process_response_with_empty_policy(self):
        request = self.factory.get(reverse('home'))
        middleware = CSPMiddleware(lambda r: HttpResponse())
        response = middleware(request)
        self.assertIn('Content-Security-Policy', response)
        self.assertEqual(response['Content-Security-Policy'], "default-src 'self'")

    def test_can_pre_process_response_with_non_empty_policy(self):
        request = self.factory.get(reverse('home'))
        middleware = CSPMiddleware(lambda r: HttpResponse())
        middleware.policy = {'default-src': ['www.example.com', 'maxcdn.bootstrapcdn.com']}
        response = middleware(request)
        self.assertIn('Content-Security-Policy', response)
        self.assertEqual(response['Content-Security-Policy'], "default-src www.example.com maxcdn.bootstrapcdn.com")

To allow editing of the build policy layout for django-csp, you can modify the build_policy function to return the csp variable before it is changed into policy_parts.

You can then refactor the addition of nonce and final string construction into new functions, such as add_nonce_to_policy and construct_csp_header, respectively. These functions can be called by build_policy to add the nonce and construct the final CSP header string.

Developers can then hook into the output of build_policy to order or append policy parts as required, and then return the outputs of add_nonce_to_policy and construct_csp_header as required.

Here's an example implementation:


def build_policy(policies, overrides=None, nonce_generator=get_nonce_generator(),
                 report_only=False):
    csp = {}
    for policy in policies:
        for name, value in policy.items():
            if name == 'nonce':
                continue
            elif name in ('default-src', 'script-src', 'style-src', 'img-src', 'connect-src', 
                 'font-src','media-src', 'object-src', 'child-src', 'frame-src', 'worker-src',
                 'manifest-src', 'base-uri', 'form-action', 'frame-ancestors',
                 'plugin-types', 'sandbox', 'navigate-to', 'block-all-mixed-content',
                 'upgrade-insecure-requests', 'require-sri-for'):
                values = [v.strip() for v in value.split(';') if v.strip()]
                if nonce_generator and name in ('script-src', 'style-src', 'default-src'):
                    values = [add_nonce(policy, v) if 'nonce' not in v else v for v in values]
                csp[name] = values

    return csp

def add_nonce_to_policy(policy, source):
    return source

def construct_csp_header(policy_parts):
    final = "; ".join(policy_parts)
    final = " ".join([final, "report-uri /csp_reports/"])
    return final

from django.test import TestCase
from django_csp.utils import build_policy

class BuildPolicyTestCase(TestCase):
    def test_build_policy(self):
        policies = [
            {'default-src': "'self'"},
            {'script-src': "'self'"},
            {'style-src': "'self'"},
            {'img-src': "'self'"},
        ]
        overrides = {'script-src': "'unsafe-inline'"}
        csp = build_policy(policies, overrides=overrides)

        expected_csp = {
            'default-src': ["'self'"],
            'script-src': ["'self'", "'unsafe-inline'"],
            'style-src': ["'self'"],
            'img-src': ["'self'"],
        }
        self.assertEqual(csp, expected_csp)

This test case creates a list of policies and an override for the script-src policy. It then calls the build_policy function with these policies and the override, and compares the resulting CSP with the expected CSP. This test ensures that the build_policy function correctly combines the policies and applies the override.

You can then use these functions in your Django views or middleware to generate customized CSP headers.

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.