-
Notifications
You must be signed in to change notification settings - Fork 107
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Post-response tools needing access to csp_nonce
after view generates response
#268
Comments
I will be able to try to reproduce this in a couple days and think through some options and share back here. Thanks for the report! |
I'm now realizing the toolbar middleware could grab this from the request on pre view side. Though it would mean the csp middleware would need to be first. I'm not sure how I feel about that as a long term solution. |
The reason it is done this way is that the post-response code has to add the nonce to the CSP header, so if you "generate" the nonce afterwards, the content is still blocked because there is no nonce in the CSP header. You could write a new attribute, like |
Gotcha that makes sense. Thank you for the clarification.
I'm not following what you're suggesting here. Do you mind elaborating a bit? Please keep in mind, this is for another library. I wouldn't have control of the views in this scenario. |
What I was thinking is that django-debug-toolbar would change this code: to something like: class DebugToolbarMiddleware:
...
def __call__(self, request):
...
# Decide whether the toolbar is active for this request.
show_toolbar = get_show_toolbar()
if not show_toolbar(request) or DebugToolbar.is_toolbar_request(request):
return self.get_response(request)
# Require CSP nonce
request.middleware_requires_csp_nonce = True
toolbar = DebugToolbar(request, self.get_response)
... and then django-csp would read it here class CSPMiddleware(MiddlewareMixin):
....
def process_response(self, request: HttpRequest, response: HttpResponseBase) -> HttpResponseBase:
...
if response.status_code in exempted_debug_codes and settings.DEBUG:
return response
# Check if other middleware needs the nonce
if getattr(request, 'middleware_requires_csp_nonce', False):
self._make_nonce()
policy_parts = self.get_policy_parts(request=request, response=response)
csp = build_policy(**asdict(policy_parts))
# Once we've written the header, accessing the `request.csp_nonce` will no longer trigger
# the nonce to be added to the header. Instead we throw an error here to catch this since
# this has security implications.
if not getattr(request, 'middleware_requires_csp_nonce', False):
setattr(request, "csp_nonce", SimpleLazyObject(self._csp_nonce_post_response)) but in writing it out, I'm thinking of other changes:
I think there is still needed some way to communicate that def init_csp_nonce_middleware(get_response):
def middleware(request):
getattr(request, "csp_nonce", None)
return get_response(request)
return middleware and then the django debug toolbar tests become: @override_settings(
MIDDLEWARE=settings.MIDDLEWARE + ["csp.middleware.CSPMiddleware", "init_csp_nonce_middleware"]
)
def test_exists(self):
... This seems better than a magic cross-project attribute. It still needs this project to leave |
I've implemented my idea in PR #269, take a look. The django-debug-toolbar tests will still need something like |
I think it might actually be best if the toolbar relies on Relevant PR: django-commons/django-debug-toolbar#2088 |
I'd rather you didn't use private members, that feels like a recipe for future breakage in bizarre ways. |
Hi folks, we're running into an issue with the django debug toolbar (#2082) with the feature implemented in #247 when trying to render extra content after the view has processed for the debug toolbar. Would it be possible for this to continue to raise the error, but also expose the nonce if it's caught? That way a person can decide that they need access to the original nonce or not.
The toolbar injects extra content into the response after the view has processed the request, so disabling the nonce at that point prevents the toolbar from adding extra static content to the response.
If the toolbar shouldn't be doing this, then I may need some help on designing how this should work.
The text was updated successfully, but these errors were encountered: