#15727: Add support for Content-Security-Policy (CSP) to core
-------------------------------+-----------------------------------------
     Reporter:  db.pub.mail@…  |                    Owner:  Anvesh Mishra
         Type:  New feature    |                   Status:  assigned
    Component:  HTTP handling  |                  Version:  dev
     Severity:  Normal         |               Resolution:
     Keywords:                 |             Triage Stage:  Accepted
    Has patch:  1              |      Needs documentation:  1
  Needs tests:  0              |  Patch needs improvement:  0
Easy pickings:  0              |                    UI/UX:  0
-------------------------------+-----------------------------------------

Comment (by Anvesh Mishra):

 Had some implementation ideas needed suggestions:
 CSP should be added to the SecurityMiddleware according to Tim Graham's
 [https://code.djangoproject.com/ticket/15727 comment], so some of the
 implementation ideas that I wanted to share are:
 1) The following settings will have to be added to
 `conf\global_settings.py`:
 {{{#!py
 SECURE_CSP = {}
 SECURE_CSP_INCLUDE_NONCE_IN = None
 SECURE_CSP_REPORT_ONLY = {}
 SECURE_CSP_EXCLUDE_URL_PREFIXES = ()
 }}}

 2) Implementation for CSP and Report-Only with nonce support in
 SecurityMiddleware:
 {{{#!py
 class SecurityMiddleware(MiddlewareMixin):
     def __init__(self, get_response):
         super().__init__(get_response)

         self.csp = settings.SECURE_CSP
         self.csp_report_only = settings.SECURE_CSP_REPORT_ONLY
         self.csp_nonce = settings.SECURE_CSP_INCLUDE_NONCE_IN

     def _make_nonce(self, request):
         if not getattr(request, '_csp_nonce', None):
             request._csp_nonce = (
                 base64
                 .b64encode(os.urandom(16))
                 .decode("ascii")
             )
         return request._csp_nonce

     def process_request(self, request):
         path = request.path.lstrip("/")
         nonce = partial(self._make_nonce, request)
         request.csp_nonce = SimpleLazyObject(nonce)
         if (
             self.redirect
             and not request.is_secure()
             and not any(pattern.search(path) for pattern in
 self.redirect_exempt)
         ):
             host = self.redirect_host or request.get_host()
             return HttpResponsePermanentRedirect(
                 "https://%s%s"; % (host, request.get_full_path())
             )

     def process_response(self, request, response):
         .................................
         if self.csp:
             csp_header = '; '.join(
                 (f'{k} {v}' for k, v in self.csp.items())
             )
             if self.csp_nonce:
                 nonce = getattr(request, '_csp_nonce', None)
                 csp_header += "; 'nonce-%s'" % nonce
             response.headers["Content-Security-Policy"] = csp_header
         if self.csp_report_only:
             csp_header = '; '.join(
                 (f'{k} {v}' for k, v in self.csp_report_only.items())
             )
             response.headers["Content-Security-Policy-Report-Only"] =
 csp_header
         return response
 }}}
 The CSP and Report-Only are repetitive so will making a method like
 csp_policy_builder be apt?
 Also this implementation is not the actual representation of the overall
 implementation it's just a snippet
 3) The CSP nonce context processor:
 {{{#!py
 def nonce(request):
     nonce = request.csp_nonce if hasattr(request, 'csp_nonce') else ''

     return {
         'CSP_NONCE': nonce
     }
 }}}

-- 
Ticket URL: <https://code.djangoproject.com/ticket/15727#comment:33>
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/01070186d7ec5ae4-470589f4-50cc-4a84-8347-6181872286d7-000000%40eu-central-1.amazonses.com.

Reply via email to