VYPR
High severityNVD Advisory· Published Mar 22, 2023· Updated Feb 25, 2025

Sentry SDK leaks sensitive session information when `sendDefaultPII` is set to `True`

CVE-2023-28117

Description

Sentry Python SDK Django integration in versions <1.14.0 could leak custom-named session/CSRF cookies to Sentry when sendDefaultPII is enabled.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Sentry Python SDK Django integration in versions <1.14.0 could leak custom-named session/CSRF cookies to Sentry when sendDefaultPII is enabled.

Vulnerability

Overview CVE-2023-28117 affects the Sentry Python SDK's Django integration prior to version 1.14.0. When sendDefaultPII is set to True and custom cookie names are used in Django settings (SESSION_COOKIE_NAME or CSRF_COOKIE_NAME), the SDK sends these sensitive cookies' values to Sentry without scrubbing [1][2]. This occurs because the SDK's default data scrubbing rules only recognize standard cookie names, leaving custom-named cookies exposed.

Exploitation

Conditions Exploitation requires three conditions: the SDK configuration must have sendDefaultPII: True, the Django settings must define custom names for SESSION_COOKIE_NAME or CSRF_COOKIE_NAME, and no custom data scrubbing rules are applied at the organization or project level to filter these custom cookies [2][4]. An attacker who gains access to Sentry issues (e.g., through compromised credentials or misconfigured permissions) could extract the leaked cookie values.

Impact

The leaked cookies could include the session cookie and CSRF token, enabling an attacker to impersonate authenticated users or perform privileged actions within the affected application [4]. This can lead to privilege escalation or account takeover depending on the role of the exposed session.

Mitigation

The vulnerability is patched in sentry-sdk version 1.14.0, which automatically detects custom cookie names from Django settings and removes them before sending data [1]. For those unable to upgrade, workarounds include using the before_send or before_send_transaction callbacks to filter cookies, or implementing server-side data scrubbing rules targeting $http.cookies or $request.cookies fields [2][4].

AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
sentry-sdkPyPI
< 1.14.01.14.0

Affected products

2

Patches

2
8c4a19a4391a

Updated changelog

https://github.com/getsentry/sentry-pythonAnton PirkerJan 23, 2023via osv
1 file changed · +32 12
  • CHANGELOG.md+32 12 modified
    @@ -4,19 +4,39 @@
     
     ### Various fixes & improvements
     
    -- Removed code coverage target (#1862) by @antonpirker
    -- feat(profiling): Add profile context to transaction (#1860) by @Zylphrex
    -- Always remove Django session related cookies. (#1842) by @antonpirker
    -- Make sure to noop when there is no DSN (#1852) by @antonpirker
    -- feat(profiling): Use co_qualname in python 3.11 (#1831) by @Zylphrex
    -- Fix middleware being patched multiple times when using FastAPI (#1841) by @JohnnyDeuss
    -- fix(opentelemetry): Use dict for sentry-trace context instead of tuple (#1847) by @AbhiPrasad
    -- fix extra dependency (#1825) by @bernardotorres
    -- Avoid import of pkg_resource with Starlette integration (#1836) by @mgu
     - Add `before_send_transaction` (#1840) by @antonpirker
    -- feat(profiling): Enable profiling for ASGI frameworks (#1824) by @Zylphrex
    -- feat(profiling): Better gevent support (#1822) by @Zylphrex
    -- fix(otel): NoOpSpan updates scope (#1834) by @Zylphrex
    +
    +  Adds a hook (similar to `before_send`) that is called for all transaction events (performance releated data).
    +
    +  Usage:
    +
    +  ```python
    +    import sentry_sdk
    +
    +    def strip_sensitive_data(event, hint):
    +        # modify event here (or return `None` if you want to drop the event entirely)
    +        return event
    +
    +    sentry_sdk.init(
    +        # ...
    +        before_send_transaction=strip_sensitive_data,
    +    )
    +  ```
    +
    +  See also: https://docs.sentry.io/platforms/python/configuration/filtering/#using-platformidentifier-namebefore-send-transaction-
    +
    +- Django: Always remove values of Django session related cookies. (#1842) by @antonpirker
    +- Profiling: Enable profiling for ASGI frameworks (#1824) by @Zylphrex
    +- Profiling: Better gevent support (#1822) by @Zylphrex
    +- Profiling: Add profile context to transaction (#1860) by @Zylphrex
    +- Profiling: Use co_qualname in python 3.11 (#1831) by @Zylphrex
    +- OpenTelemetry: fix Use dict for sentry-trace context instead of tuple (#1847) by @AbhiPrasad
    +- OpenTelemetry: fix extra dependency (#1825) by @bernardotorres
    +- OpenTelemetry: fix NoOpSpan updates scope (#1834) by @Zylphrex
    +- OpenTelemetry: Make sure to noop when there is no DSN (#1852) by @antonpirker
    +- FastAPI: Fix middleware being patched multiple times (#1841) by @JohnnyDeuss
    +- Starlette: Avoid import of pkg_resource with Starlette integration (#1836) by @mgu
    +- Removed code coverage target (#1862) by @antonpirker
     
     ## 1.13.0
     
    
d5152331f58d

Always remove Django session related cookies. (#1842)

https://github.com/getsentry/sentry-pythonAnton PirkerJan 20, 2023via ghsa-ref
4 files changed · +140 3
  • sentry_sdk/consts.py+2 0 modified
    @@ -44,6 +44,8 @@
     DEFAULT_QUEUE_SIZE = 100
     DEFAULT_MAX_BREADCRUMBS = 100
     
    +SENSITIVE_DATA_SUBSTITUTE = "[Filtered]"
    +
     
     class INSTRUMENTER:
         SENTRY = "sentry"
    
  • sentry_sdk/integrations/django/__init__.py+17 3 modified
    @@ -6,13 +6,14 @@
     import weakref
     
     from sentry_sdk._types import MYPY
    -from sentry_sdk.consts import OP
    +from sentry_sdk.consts import OP, SENSITIVE_DATA_SUBSTITUTE
     from sentry_sdk.hub import Hub, _should_send_default_pii
     from sentry_sdk.scope import add_global_event_processor
     from sentry_sdk.serializer import add_global_repr_processor
     from sentry_sdk.tracing import SOURCE_FOR_STYLE, TRANSACTION_SOURCE_URL
     from sentry_sdk.tracing_utils import record_sql_queries
     from sentry_sdk.utils import (
    +    AnnotatedValue,
         HAS_REAL_CONTEXTVARS,
         CONTEXTVARS_ERROR_MESSAGE,
         logger,
    @@ -28,6 +29,7 @@
     
     try:
         from django import VERSION as DJANGO_VERSION
    +    from django.conf import settings as django_settings
         from django.core import signals
     
         try:
    @@ -476,8 +478,20 @@ def env(self):
             return self.request.META
     
         def cookies(self):
    -        # type: () -> Dict[str, str]
    -        return self.request.COOKIES
    +        # type: () -> Dict[str, Union[str, AnnotatedValue]]
    +        privacy_cookies = [
    +            django_settings.CSRF_COOKIE_NAME,
    +            django_settings.SESSION_COOKIE_NAME,
    +        ]
    +
    +        clean_cookies = {}  # type: Dict[str, Union[str, AnnotatedValue]]
    +        for (key, val) in self.request.COOKIES.items():
    +            if key in privacy_cookies:
    +                clean_cookies[key] = SENSITIVE_DATA_SUBSTITUTE
    +            else:
    +                clean_cookies[key] = val
    +
    +        return clean_cookies
     
         def raw_data(self):
             # type: () -> bytes
    
  • sentry_sdk/utils.py+18 0 modified
    @@ -370,6 +370,24 @@ def removed_because_over_size_limit(cls):
                 },
             )
     
    +    @classmethod
    +    def substituted_because_contains_sensitive_data(cls):
    +        # type: () -> AnnotatedValue
    +        """The actual value was removed because it contained sensitive information."""
    +        from sentry_sdk.consts import SENSITIVE_DATA_SUBSTITUTE
    +
    +        return AnnotatedValue(
    +            value=SENSITIVE_DATA_SUBSTITUTE,
    +            metadata={
    +                "rem": [  # Remark
    +                    [
    +                        "!config",  # Because of SDK configuration (in this case the config is the hard coded removal of certain django cookies)
    +                        "s",  # The fields original value was substituted
    +                    ]
    +                ]
    +            },
    +        )
    +
     
     if MYPY:
         from typing import TypeVar
    
  • tests/integrations/django/test_data_scrubbing.py+103 0 added
    @@ -0,0 +1,103 @@
    +from functools import partial
    +import pytest
    +import pytest_django
    +
    +from werkzeug.test import Client
    +
    +from sentry_sdk.integrations.django import DjangoIntegration
    +
    +from tests.integrations.django.myapp.wsgi import application
    +
    +try:
    +    from django.urls import reverse
    +except ImportError:
    +    from django.core.urlresolvers import reverse
    +
    +
    +# Hack to prevent from experimental feature introduced in version `4.3.0` in `pytest-django` that
    +# requires explicit database allow from failing the test
    +pytest_mark_django_db_decorator = partial(pytest.mark.django_db)
    +try:
    +    pytest_version = tuple(map(int, pytest_django.__version__.split(".")))
    +    if pytest_version > (4, 2, 0):
    +        pytest_mark_django_db_decorator = partial(
    +            pytest.mark.django_db, databases="__all__"
    +        )
    +except ValueError:
    +    if "dev" in pytest_django.__version__:
    +        pytest_mark_django_db_decorator = partial(
    +            pytest.mark.django_db, databases="__all__"
    +        )
    +except AttributeError:
    +    pass
    +
    +
    +@pytest.fixture
    +def client():
    +    return Client(application)
    +
    +
    +@pytest.mark.forked
    +@pytest_mark_django_db_decorator()
    +def test_scrub_django_session_cookies_removed(
    +    sentry_init,
    +    client,
    +    capture_events,
    +):
    +    sentry_init(integrations=[DjangoIntegration()], send_default_pii=False)
    +    events = capture_events()
    +    client.set_cookie("localhost", "sessionid", "123")
    +    client.set_cookie("localhost", "csrftoken", "456")
    +    client.set_cookie("localhost", "foo", "bar")
    +    client.get(reverse("view_exc"))
    +
    +    (event,) = events
    +    assert "cookies" not in event["request"]
    +
    +
    +@pytest.mark.forked
    +@pytest_mark_django_db_decorator()
    +def test_scrub_django_session_cookies_filtered(
    +    sentry_init,
    +    client,
    +    capture_events,
    +):
    +    sentry_init(integrations=[DjangoIntegration()], send_default_pii=True)
    +    events = capture_events()
    +    client.set_cookie("localhost", "sessionid", "123")
    +    client.set_cookie("localhost", "csrftoken", "456")
    +    client.set_cookie("localhost", "foo", "bar")
    +    client.get(reverse("view_exc"))
    +
    +    (event,) = events
    +    assert event["request"]["cookies"] == {
    +        "sessionid": "[Filtered]",
    +        "csrftoken": "[Filtered]",
    +        "foo": "bar",
    +    }
    +
    +
    +@pytest.mark.forked
    +@pytest_mark_django_db_decorator()
    +def test_scrub_django_custom_session_cookies_filtered(
    +    sentry_init,
    +    client,
    +    capture_events,
    +    settings,
    +):
    +    settings.SESSION_COOKIE_NAME = "my_sess"
    +    settings.CSRF_COOKIE_NAME = "csrf_secret"
    +
    +    sentry_init(integrations=[DjangoIntegration()], send_default_pii=True)
    +    events = capture_events()
    +    client.set_cookie("localhost", "my_sess", "123")
    +    client.set_cookie("localhost", "csrf_secret", "456")
    +    client.set_cookie("localhost", "foo", "bar")
    +    client.get(reverse("view_exc"))
    +
    +    (event,) = events
    +    assert event["request"]["cookies"] == {
    +        "my_sess": "[Filtered]",
    +        "csrf_secret": "[Filtered]",
    +        "foo": "bar",
    +    }
    

Vulnerability mechanics

Root cause

"The Django integration's cookie extractor returned raw cookie values without filtering session and CSRF cookies, even when sendDefaultPII was enabled."

Attack vector

An attacker who can cause a Django application to send an error or transaction event to Sentry (e.g., by triggering an unhandled exception) can cause the session cookie and CSRF cookie values to be included in the event payload. The vulnerability is exploitable when the SDK configuration has `sendDefaultPII` set to `True` and the Django settings use custom names for `SESSION_COOKIE_NAME` or `CSRF_COOKIE_NAME` without corresponding server-side data scrubbing rules. The attacker does not need direct network access to Sentry's infrastructure; the leaked cookies become accessible to anyone with read access to the Sentry issue, enabling session hijacking or privilege escalation.

Affected code

The Django integration's `DjangoRequestExtractor.cookies()` method in `sentry_sdk/integrations/django/__init__.py` previously returned the raw `request.COOKIES` dictionary without filtering. The patch adds logic to read `django_settings.CSRF_COOKIE_NAME` and `django_settings.SESSION_COOKIE_NAME` and replaces their values with the constant `SENSITIVE_DATA_SUBSTITUTE` (`"[Filtered]"`) defined in `sentry_sdk/consts.py` [patch_id=1640926].

What the fix does

The patch modifies `DjangoRequestExtractor.cookies()` to read the configured `CSRF_COOKIE_NAME` and `SESSION_COOKIE_NAME` from Django settings and replace those cookie values with `"[Filtered]"` before the event is sent to Sentry [patch_id=1640926]. A new `AnnotatedValue.substituted_because_contains_sensitive_data()` class method was added to `sentry_sdk/utils.py` to produce a metadata-annotated substitute value, and the constant `SENSITIVE_DATA_SUBSTITUTE` was defined in `sentry_sdk/consts.py`. This ensures that even when `sendDefaultPii=True`, the sensitive Django cookies are always scrubbed regardless of their configured names.

Preconditions

  • configSentry SDK configuration must have sendDefaultPII set to True
  • configDjango settings must use custom names for SESSION_COOKIE_NAME or CSRF_COOKIE_NAME
  • configNo server-side data scrubbing rules configured in Sentry to account for the custom cookie names

Generated on May 23, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.