diff --git a/pyproject.toml b/pyproject.toml index aa443b1f35..d4a225a9ee 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -92,7 +92,7 @@ dependencies = [ "redis==5.0.*", "reportlab==4.2.*", "requests==2.31.*", - "sentry-sdk==1.45.*", + "sentry-sdk==2.5.*", "sepaxml==2.6.*", "slimit", "static3==0.7.*", diff --git a/src/pretix/sentry.py b/src/pretix/sentry.py index 451f8ea367..56eee6239f 100644 --- a/src/pretix/sentry.py +++ b/src/pretix/sentry.py @@ -19,60 +19,13 @@ # You should have received a copy of the GNU Affero General Public License along with this program. If not, see # . # -import re import weakref -from collections import OrderedDict from celery.exceptions import Retry from sentry_sdk import Hub from sentry_sdk.integrations import django as djangosentry from sentry_sdk.utils import capture_internal_exceptions -MASK = '*' * 8 -KEYS = frozenset([ - 'password', - 'secret', - 'passwd', - 'authorization', - 'api_key', - 'apikey', - 'sentry_dsn', - 'access_token', - 'session', -]) -VALUES_RE = re.compile(r'^(?:\d[ -]*?){13,16}$') - - -def scrub_data(data): - if isinstance(data, dict): - for k, v in data.items(): - if isinstance(k, bytes): - key = k.decode('utf-8', 'replace') - else: - key = k - key = key.lower() - data[k] = scrub_data(v) - for blk in KEYS: - if blk in key: - data[k] = MASK - elif isinstance(data, list): - for i, l in enumerate(list(data)): - data[i] = scrub_data(l) - elif isinstance(data, str): - if '=' in data: - # at this point we've assumed it's a standard HTTP query - # or cookie - if '&' in data: - delimiter = '&' - else: - delimiter = ';' - - qd = scrub_data(OrderedDict(e.split('=', 1) if '=' in e else (e, None) for e in data.split(delimiter))) - return delimiter.join((k + '=' + v if v is not None else k) for k, v in qd.items()) - if VALUES_RE.match(data): - return MASK - return data - def _make_event_processor(weak_request, integration): def event_processor(event, hint): @@ -82,8 +35,6 @@ def _make_event_processor(weak_request, integration): with capture_internal_exceptions(): djangosentry._set_user_info(request, event) - request_info = event.setdefault("request", {}) - request_info["cookies"] = dict(request.COOKIES) # Sentry's DjangoIntegration already sets the transaction, but it gets confused by our multi-domain stuff # where the URL resolver changes in the middleware stack. Additionally, we'd like to get the method. @@ -96,15 +47,6 @@ def _make_event_processor(weak_request, integration): request.method, url ) - - # We want to scrub data not only from the request, but from traceback frames as well! - scrub_data(event.get("request", {})) - if 'exception' in event: - exc = event.get("exception", {}) - for val in exc.get('values', []): - stack = val.get('stacktrace', {}) - for frame in stack.get('frames', []): - scrub_data(frame['vars']) return event return event_processor diff --git a/src/pretix/settings.py b/src/pretix/settings.py index a202a2c3f8..ae13e96554 100644 --- a/src/pretix/settings.py +++ b/src/pretix/settings.py @@ -629,15 +629,21 @@ LOGGING = { SENTRY_ENABLED = False if config.has_option('sentry', 'dsn') and not any(c in sys.argv for c in ('shell', 'shell_scoped', 'shell_plus')): + import django.db.models.signals import sentry_sdk from sentry_sdk.integrations.celery import CeleryIntegration from sentry_sdk.integrations.logging import ( LoggingIntegration, ignore_logger, ) + from sentry_sdk.scrubber import EventScrubber, DEFAULT_DENYLIST from .sentry import PretixSentryIntegration, setup_custom_filters SENTRY_TOKEN = config.get('sentry', 'traces_sample_token', fallback='') + pretix_denylist = DEFAULT_DENYLIST + [ + "access_token", + "sentry_dsn", + ] def traces_sampler(sampling_context): qs = sampling_context.get('wsgi_environ', {}).get('QUERY_STRING', '') @@ -649,7 +655,12 @@ if config.has_option('sentry', 'dsn') and not any(c in sys.argv for c in ('shell sentry_sdk.init( dsn=config.get('sentry', 'dsn'), integrations=[ - PretixSentryIntegration(), + PretixSentryIntegration( + signals_denylist=[ + django.db.models.signals.pre_init, + django.db.models.signals.post_init, + ] + ), CeleryIntegration(), LoggingIntegration( level=logging.INFO, @@ -659,6 +670,7 @@ if config.has_option('sentry', 'dsn') and not any(c in sys.argv for c in ('shell traces_sampler=traces_sampler, environment=urlparse(SITE_URL).netloc, release=__version__, + event_scrubber=EventScrubber(denylist=pretix_denylist, recursive=True), send_default_pii=False, propagate_traces=False, # see https://github.com/getsentry/sentry-python/issues/1717 )