torchbox / django-pattern-library

UI pattern libraries for Django templates
https://torchbox.github.io/django-pattern-library/
BSD 3-Clause "New" or "Revised" License
360 stars 44 forks source link

CSP issues #208

Open dgabrahams opened 1 year ago

dgabrahams commented 1 year ago

Whilst in the process of adding a Content Security Policy to a Wagtail site I found that the Pattern Library is not compliant. I raised this issue to request that the Pattern Library be made CSP compliant.

Working on the philosophy that a weak CSP is better than no CSP I have added some custom middleware to get around the issue, please see an example below:

class CSPOverrideMiddleware(MiddlewareMixin):
    """
    Custom middleware to override Content Security Policy directives.
    Add to MIDDLEWARE list after official django-csp CSPMiddleware.
    """

    def process_request(self, request):
        prefix = ("/pattern-library")
        if request.path_info.startswith(prefix):
            # Remove nonce value otherwise 'unsafe-inline' will not work.
            request.csp_nonce = None

    def process_response(self, request, response):
        # Add CSP sources to enable pages to work.
        if request.path_info.startswith("/pattern-library"):
            response._csp_update = {
                "style-src": "'unsafe-inline'",
                "script-src": "'unsafe-inline'",
                "img-src": "https://via.placeholder.com",
            }

        return response

Still in the process of testing but adding here to share the general approach for a (hopefully) temporary workaround. Thanks.

thibaudcolas commented 1 year ago

Thanks for the report @dgabrahams! I think we’d love to make this conform to a strict CSP (default-src 'self' ?) for people who need this.

Do you have further insights on which parts of the project weren’t working? Quickly looking at our online demo, the only two issues I see is usage of a <style> tag to load our stylesheets, and one element with a style attribute.

dgabrahams commented 1 year ago

Hi @thibaudcolas - nothing specific at this point I have to admit my efforts are currently focused on other issues regarding my current project. Doing a quick search of the codebase revealed two inline styles (one set by JS and the other as part of a sprite):

pattern_library/static/pattern_library/src/js/components/iframe.js
tests/templates/patterns/atoms/sprites/sprites.html

The way I am currently tackling CSP is to refactor inline styles to a stylesheet and using JS to add/remove classes. CSS and JS files are added to the page using a nonce value on page load.

I am not sure on your own vision for implementation but if something similar to what I suggested is pursued either hash or nonce values might be the only way. I have preference of nonce over hash values.

thibaudcolas commented 1 year ago

Thanks for following up. My preference would be to to replace the sprites.html display none with a CSS class. For iframe.js, I don’t think there’s anything that needs changing? Inline styles set in JS via elt.style. would be allowed by default-src 'self' I believe.

For the other <style> tag to load our stylesheet, it really should be changed in Webpack to create and load a CSS file.