Skip to content

Commit d515233

Browse files
authored
Always remove Django session related cookies. (#1842)
* Always remove Django session related cookies.
1 parent 032ea57 commit d515233

File tree

4 files changed

+140
-3
lines changed

4 files changed

+140
-3
lines changed

sentry_sdk/consts.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444
DEFAULT_QUEUE_SIZE = 100
4545
DEFAULT_MAX_BREADCRUMBS = 100
4646

47+
SENSITIVE_DATA_SUBSTITUTE = "[Filtered]"
48+
4749

4850
class INSTRUMENTER:
4951
SENTRY = "sentry"

sentry_sdk/integrations/django/__init__.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@
66
import weakref
77

88
from sentry_sdk._types import MYPY
9-
from sentry_sdk.consts import OP
9+
from sentry_sdk.consts import OP, SENSITIVE_DATA_SUBSTITUTE
1010
from sentry_sdk.hub import Hub, _should_send_default_pii
1111
from sentry_sdk.scope import add_global_event_processor
1212
from sentry_sdk.serializer import add_global_repr_processor
1313
from sentry_sdk.tracing import SOURCE_FOR_STYLE, TRANSACTION_SOURCE_URL
1414
from sentry_sdk.tracing_utils import record_sql_queries
1515
from sentry_sdk.utils import (
16+
AnnotatedValue,
1617
HAS_REAL_CONTEXTVARS,
1718
CONTEXTVARS_ERROR_MESSAGE,
1819
logger,
@@ -28,6 +29,7 @@
2829

2930
try:
3031
from django import VERSION as DJANGO_VERSION
32+
from django.conf import settings as django_settings
3133
from django.core import signals
3234

3335
try:
@@ -476,8 +478,20 @@ def env(self):
476478
return self.request.META
477479

478480
def cookies(self):
479-
# type: () -> Dict[str, str]
480-
return self.request.COOKIES
481+
# type: () -> Dict[str, Union[str, AnnotatedValue]]
482+
privacy_cookies = [
483+
django_settings.CSRF_COOKIE_NAME,
484+
django_settings.SESSION_COOKIE_NAME,
485+
]
486+
487+
clean_cookies = {} # type: Dict[str, Union[str, AnnotatedValue]]
488+
for (key, val) in self.request.COOKIES.items():
489+
if key in privacy_cookies:
490+
clean_cookies[key] = SENSITIVE_DATA_SUBSTITUTE
491+
else:
492+
clean_cookies[key] = val
493+
494+
return clean_cookies
481495

482496
def raw_data(self):
483497
# type: () -> bytes

sentry_sdk/utils.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,24 @@ def removed_because_over_size_limit(cls):
370370
},
371371
)
372372

373+
@classmethod
374+
def substituted_because_contains_sensitive_data(cls):
375+
# type: () -> AnnotatedValue
376+
"""The actual value was removed because it contained sensitive information."""
377+
from sentry_sdk.consts import SENSITIVE_DATA_SUBSTITUTE
378+
379+
return AnnotatedValue(
380+
value=SENSITIVE_DATA_SUBSTITUTE,
381+
metadata={
382+
"rem": [ # Remark
383+
[
384+
"!config", # Because of SDK configuration (in this case the config is the hard coded removal of certain django cookies)
385+
"s", # The fields original value was substituted
386+
]
387+
]
388+
},
389+
)
390+
373391

374392
if MYPY:
375393
from typing import TypeVar
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
from functools import partial
2+
import pytest
3+
import pytest_django
4+
5+
from werkzeug.test import Client
6+
7+
from sentry_sdk.integrations.django import DjangoIntegration
8+
9+
from tests.integrations.django.myapp.wsgi import application
10+
11+
try:
12+
from django.urls import reverse
13+
except ImportError:
14+
from django.core.urlresolvers import reverse
15+
16+
17+
# Hack to prevent from experimental feature introduced in version `4.3.0` in `pytest-django` that
18+
# requires explicit database allow from failing the test
19+
pytest_mark_django_db_decorator = partial(pytest.mark.django_db)
20+
try:
21+
pytest_version = tuple(map(int, pytest_django.__version__.split(".")))
22+
if pytest_version > (4, 2, 0):
23+
pytest_mark_django_db_decorator = partial(
24+
pytest.mark.django_db, databases="__all__"
25+
)
26+
except ValueError:
27+
if "dev" in pytest_django.__version__:
28+
pytest_mark_django_db_decorator = partial(
29+
pytest.mark.django_db, databases="__all__"
30+
)
31+
except AttributeError:
32+
pass
33+
34+
35+
@pytest.fixture
36+
def client():
37+
return Client(application)
38+
39+
40+
@pytest.mark.forked
41+
@pytest_mark_django_db_decorator()
42+
def test_scrub_django_session_cookies_removed(
43+
sentry_init,
44+
client,
45+
capture_events,
46+
):
47+
sentry_init(integrations=[DjangoIntegration()], send_default_pii=False)
48+
events = capture_events()
49+
client.set_cookie("localhost", "sessionid", "123")
50+
client.set_cookie("localhost", "csrftoken", "456")
51+
client.set_cookie("localhost", "foo", "bar")
52+
client.get(reverse("view_exc"))
53+
54+
(event,) = events
55+
assert "cookies" not in event["request"]
56+
57+
58+
@pytest.mark.forked
59+
@pytest_mark_django_db_decorator()
60+
def test_scrub_django_session_cookies_filtered(
61+
sentry_init,
62+
client,
63+
capture_events,
64+
):
65+
sentry_init(integrations=[DjangoIntegration()], send_default_pii=True)
66+
events = capture_events()
67+
client.set_cookie("localhost", "sessionid", "123")
68+
client.set_cookie("localhost", "csrftoken", "456")
69+
client.set_cookie("localhost", "foo", "bar")
70+
client.get(reverse("view_exc"))
71+
72+
(event,) = events
73+
assert event["request"]["cookies"] == {
74+
"sessionid": "[Filtered]",
75+
"csrftoken": "[Filtered]",
76+
"foo": "bar",
77+
}
78+
79+
80+
@pytest.mark.forked
81+
@pytest_mark_django_db_decorator()
82+
def test_scrub_django_custom_session_cookies_filtered(
83+
sentry_init,
84+
client,
85+
capture_events,
86+
settings,
87+
):
88+
settings.SESSION_COOKIE_NAME = "my_sess"
89+
settings.CSRF_COOKIE_NAME = "csrf_secret"
90+
91+
sentry_init(integrations=[DjangoIntegration()], send_default_pii=True)
92+
events = capture_events()
93+
client.set_cookie("localhost", "my_sess", "123")
94+
client.set_cookie("localhost", "csrf_secret", "456")
95+
client.set_cookie("localhost", "foo", "bar")
96+
client.get(reverse("view_exc"))
97+
98+
(event,) = events
99+
assert event["request"]["cookies"] == {
100+
"my_sess": "[Filtered]",
101+
"csrf_secret": "[Filtered]",
102+
"foo": "bar",
103+
}

0 commit comments

Comments
 (0)