#33180: Debug 500 HTML broken with strict Content-Security-Policy (CSP)
---------------------------------+--------------------------------------
     Reporter:  Adam Johnson     |                    Owner:  (none)
         Type:  Bug              |                   Status:  new
    Component:  Error reporting  |                  Version:  dev
     Severity:  Normal           |               Resolution:
     Keywords:                   |             Triage Stage:  Unreviewed
    Has patch:  0                |      Needs documentation:  0
  Needs tests:  0                |  Patch needs improvement:  0
Easy pickings:  0                |                    UI/UX:  0
---------------------------------+--------------------------------------
Description changed by Adam Johnson:

Old description:

> When using a strict CSP header, the debug view is broken as the inline
> CSS and JS get blocked by the browser. The page is somewhat usable as all
> the text is all visible, but it isn't particularly friendly or
> necessarily obvious why it's broken.
>
> For example:
>
> [[Image(https://code.djangoproject.com/attachment/ticket/33180/error.png)]]
>
> I thought of a couple of potential fixes:
>
> 1. Make the debug http response a special class that deletes any CSP
> header added to it. This would work for most cases but not if the CSP
> header is added outside of Django (WSGI middleware, a server wrapping
> runserver).
> 2. Move the CSS and JS to separate URL's so they're compatible with CSP.
> They could be served by a special route/path in `runserver`.
>
> I am personally leaning towards #2 - even though it's more complex, it is
> more general.
>
> There's also some opportunity to modernize the CSS and JS in the debug
> page a bit, such as rewriting use of window.onload and onclick handlers.
>
> To reproduce, you can save the below as `app.py` and run `python app.py
> runserver`:
>
> {{{
> import sys
>
> from django.conf import settings
> from django.urls import path
>
> settings.configure(
>     DEBUG=True,
>     ROOT_URLCONF=__name__,
>     SECRET_KEY="django-insecure-
> r42jn$xf4g+=w@=l#m6ghqo0!$icww-h4+$5gojq(1ld$x%!6f",
>     MIDDLEWARE=[f"{__name__}.CSPMiddleware"],
> )
>

> class CSPMiddleware:
>     def __init__(self, get_response):
>         self.get_response = get_response
>
>     def __call__(self, request):
>         response = self.get_response(request)
>         response[
>             "Content-Security-Policy"
>         ] = "object-src 'none'; base-uri 'none'; default-src 'self';"
>         return response
>

> def index(request):
>     1 / 0
>

> urlpatterns = [path("", index)]
>
> if __name__ == "__main__":
>     from django.core.management import execute_from_command_line
>
>     execute_from_command_line(sys.argv)
> }}}

New description:

 When using a strict CSP header, the debug view is broken as the inline CSS
 and JS get blocked by the browser. The page is somewhat usable as all the
 text is all visible, but it isn't particularly friendly or necessarily
 obvious why it's broken.

 For example:

 [[Image(ticket:33180:error.png)]]

 I thought of a couple of potential fixes:

 1. Make the debug http response a special class that deletes any CSP
 header added to it. This would work for most cases but not if the CSP
 header is added outside of Django (WSGI middleware, a server wrapping
 runserver).
 2. Move the CSS and JS to separate URL's so they're compatible with CSP.
 They could be served by a special route/path in `runserver`.

 I am personally leaning towards #2 - even though it's more complex, it is
 more general.

 There's also some opportunity to modernize the CSS and JS in the debug
 page a bit, such as rewriting use of window.onload and onclick handlers.

 To reproduce, you can save the below as `app.py` and run `python app.py
 runserver`:

 {{{
 import sys

 from django.conf import settings
 from django.urls import path

 settings.configure(
     DEBUG=True,
     ROOT_URLCONF=__name__,
     SECRET_KEY="django-insecure-
 r42jn$xf4g+=w@=l#m6ghqo0!$icww-h4+$5gojq(1ld$x%!6f",
     MIDDLEWARE=[f"{__name__}.CSPMiddleware"],
 )


 class CSPMiddleware:
     def __init__(self, get_response):
         self.get_response = get_response

     def __call__(self, request):
         response = self.get_response(request)
         response[
             "Content-Security-Policy"
         ] = "object-src 'none'; base-uri 'none'; default-src 'self';"
         return response


 def index(request):
     1 / 0


 urlpatterns = [path("", index)]

 if __name__ == "__main__":
     from django.core.management import execute_from_command_line

     execute_from_command_line(sys.argv)
 }}}

--

-- 
Ticket URL: <https://code.djangoproject.com/ticket/33180#comment:2>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/068.dbde5a95ec817a2865bdecd03fae0766%40djangoproject.com.

Reply via email to