forked from CGM_Public/pretix_original
Stripe/Middleware: Move CSP to signal (#3465)
This commit is contained in:
@@ -26,7 +26,7 @@ from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
|
||||
from django.conf import settings
|
||||
from django.http import Http404, HttpRequest, HttpResponse
|
||||
from django.middleware.common import CommonMiddleware
|
||||
from django.urls import get_script_prefix
|
||||
from django.urls import get_script_prefix, resolve
|
||||
from django.utils import timezone, translation
|
||||
from django.utils.cache import patch_vary_headers
|
||||
from django.utils.deprecation import MiddlewareMixin
|
||||
@@ -230,6 +230,8 @@ class SecurityMiddleware(MiddlewareMixin):
|
||||
)
|
||||
|
||||
def process_response(self, request, resp):
|
||||
url = resolve(request.path_info)
|
||||
|
||||
if settings.DEBUG and resp.status_code >= 400:
|
||||
# Don't use CSP on debug error page as it breaks of Django's fancy error
|
||||
# pages
|
||||
@@ -249,20 +251,26 @@ class SecurityMiddleware(MiddlewareMixin):
|
||||
|
||||
h = {
|
||||
'default-src': ["{static}"],
|
||||
'script-src': ['{static}', 'https://checkout.stripe.com', 'https://js.stripe.com', 'https://pay.google.com'],
|
||||
'script-src': ['{static}'],
|
||||
'object-src': ["'none'"],
|
||||
'frame-src': ['{static}', 'https://checkout.stripe.com', 'https://js.stripe.com'],
|
||||
'frame-src': ['{static}'],
|
||||
'style-src': ["{static}", "{media}"],
|
||||
'connect-src': ["{dynamic}", "{media}", "https://checkout.stripe.com"],
|
||||
'img-src': ["{static}", "{media}", "data:", "https://*.stripe.com"] + img_src,
|
||||
'connect-src': ["{dynamic}", "{media}"],
|
||||
'img-src': ["{static}", "{media}", "data:"] + img_src,
|
||||
'font-src': ["{static}"],
|
||||
'media-src': ["{static}", "data:"],
|
||||
# form-action is not only used to match on form actions, but also on URLs
|
||||
# form-actions redirect to. In the context of e.g. payment providers or
|
||||
# single-sign-on this can be nearly anything so we cannot really restrict
|
||||
# single-sign-on this can be nearly anything, so we cannot really restrict
|
||||
# this. However, we'll restrict it to HTTPS.
|
||||
'form-action': ["{dynamic}", "https:"] + (['http:'] if settings.SITE_URL.startswith('http://') else []),
|
||||
}
|
||||
# Only include pay.google.com for wallet detection purposes on the Payment selection page
|
||||
if (
|
||||
url.url_name == "event.order.pay.change" or
|
||||
(url.url_name == "event.checkout" and url.kwargs['step'] == "payment")
|
||||
):
|
||||
h['script-src'].append('https://pay.google.com')
|
||||
if settings.LOG_CSP:
|
||||
h['report-uri'] = ["/csp_report/"]
|
||||
if 'Content-Security-Policy' in resp:
|
||||
|
||||
@@ -24,18 +24,22 @@ from collections import OrderedDict
|
||||
|
||||
from django import forms
|
||||
from django.dispatch import receiver
|
||||
from django.http import HttpRequest
|
||||
from django.template.loader import get_template
|
||||
from django.urls import resolve, reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from paypalhttp import HttpResponse
|
||||
|
||||
from pretix.base.forms import SecretKeySettingsField
|
||||
from pretix.base.middleware import _merge_csp, _parse_csp, _render_csp
|
||||
from pretix.base.settings import settings_hierarkey
|
||||
from pretix.base.signals import (
|
||||
logentry_display, register_global_settings, register_payment_providers,
|
||||
)
|
||||
from pretix.control.signals import nav_organizer
|
||||
from pretix.plugins.stripe.forms import StripeKeyValidator
|
||||
from pretix.presale.signals import html_head
|
||||
from pretix.plugins.stripe.payment import StripeMethod
|
||||
from pretix.presale.signals import html_head, process_response
|
||||
|
||||
|
||||
@receiver(register_payment_providers, dispatch_uid="payment_stripe")
|
||||
@@ -178,3 +182,34 @@ def nav_o(sender, request, organizer, **kwargs):
|
||||
'active': 'settings.connect' in url.url_name,
|
||||
}]
|
||||
return []
|
||||
|
||||
|
||||
@receiver(signal=process_response, dispatch_uid="stripe_middleware_resp")
|
||||
def signal_process_response(sender, request: HttpRequest, response: HttpResponse, **kwargs):
|
||||
provider = StripeMethod(sender)
|
||||
url = resolve(request.path_info)
|
||||
|
||||
if provider.settings.get('_enabled', as_type=bool) and (
|
||||
url.url_name == "event.order.pay.change" or
|
||||
url.url_name == "event.order.pay" or
|
||||
(url.url_name == "event.checkout" and url.kwargs['step'] == "payment") or
|
||||
(url.namespace == "plugins:stripe" and url.url_name in ["sca", "sca.return"])
|
||||
):
|
||||
if 'Content-Security-Policy' in response:
|
||||
h = _parse_csp(response['Content-Security-Policy'])
|
||||
else:
|
||||
h = {}
|
||||
|
||||
# https://stripe.com/docs/security/guide#content-security-policy
|
||||
csps = {
|
||||
'connect-src': ['https://api.stripe.com'],
|
||||
'frame-src': ['https://js.stripe.com', 'https://hooks.stripe.com'],
|
||||
'script-src': ['https://js.stripe.com'],
|
||||
}
|
||||
|
||||
_merge_csp(h, csps)
|
||||
|
||||
if h:
|
||||
response['Content-Security-Policy'] = _render_csp(h)
|
||||
|
||||
return response
|
||||
|
||||
Reference in New Issue
Block a user