Skip to content

Commit cd6348d

Browse files
committed
feat: send_default_pii flag
1 parent 0d2d6e3 commit cd6348d

File tree

8 files changed

+63
-12
lines changed

8 files changed

+63
-12
lines changed

.flake8

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[flake8]
2-
ignore = E203, E266, E501, W503, E402
2+
ignore = E203, E266, E501, W503, E402, E731
33
max-line-length = 80
44
max-complexity = 18
55
select = B,C,E,F,W,T4,B9

docs/django.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,16 @@ In your ``settings.py``:
99

1010
* All exceptions are reported.
1111

12-
* Request data is attached to your events.
12+
* A bit of data is attached to each event:
1313

14-
* The current user ID, email and username from ``django.contrib.auth`` is
15-
attached to your events.
14+
* Personally identifiable information (such as user ids, usernames,
15+
cookies, authorization headers, ip addresses) is excluded unless
16+
``send_default_pii`` is set to ``true``. See ``README.md``, section "PII"
17+
18+
* Request data is attached to all events.
19+
20+
* If you have ``django.contrib.auth`` installed and configured, user data
21+
(current user id, email address, username) is attached to the event.
1622

1723
* Logging with any logger will create breadcrumbs. See logging docs for more
1824
information.

docs/flask.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Using Sentry with Flask
22

3+
34
from sentry_sdk.integrations.flask import FlaskIntegration
45
from sentry_sdk import init
56

@@ -14,7 +15,16 @@
1415
* The Flask integration will be installed for all of your apps. It hooks into
1516
Flask's signals, not anything on the app object.
1617

17-
* Request data is attached to all events.
18+
* A bit of data is attached to each event:
19+
20+
* Personally identifiable information (such as user ids, usernames,
21+
cookies, authorization headers, ip addresses) is excluded unless
22+
``send_default_pii`` is set to ``true``. See ``README.md``, section "PII"
23+
24+
* Request data is attached to all events.
25+
26+
* If you have Flask-Login installed and configured, user data is attached to
27+
the event.
1828

1929
* All exceptions leading to a Internal Server Error are reported.
2030

sentry_sdk/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ def _prepare_event(self, event, scope):
8686
):
8787
raise SkipEvent()
8888

89-
event = strip_event(event)
89+
event = strip_event(event, client=self)
9090
event = flatten_metadata(event)
9191
return event
9292

sentry_sdk/consts.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"dist": None,
1616
"transport": None,
1717
"sample_rate": 1.0,
18+
"send_default_pii": False,
1819
}
1920

2021
SDK_INFO = {"name": "sentry-python", "version": VERSION}

sentry_sdk/stripping.py

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ def inner(obj):
2323
rv[k], meta[k] = inner(v)
2424
if meta[k] is None:
2525
del meta[k]
26+
if rv[k] is None:
27+
del rv[k]
2628
return rv, (meta or None)
2729
if isinstance(obj, Sequence) and not isinstance(obj, (text_type, bytes)):
2830
rv = []
@@ -43,7 +45,7 @@ def inner(obj):
4345
return obj
4446

4547

46-
def strip_event(event):
48+
def strip_event(event, client=None):
4749
old_frames = event.get("stacktrace", {}).get("frames", None)
4850
if old_frames:
4951
event["stacktrace"]["frames"] = [strip_frame(frame) for frame in old_frames]
@@ -52,6 +54,32 @@ def strip_event(event):
5254
if old_request_data:
5355
event["request"]["data"] = strip_databag(old_request_data)
5456

57+
if not client or not client.options["send_default_pii"]:
58+
event = strip_default_pii(event)
59+
60+
return event
61+
62+
63+
def strip_default_pii(event):
64+
gone = lambda: AnnotatedValue(None, {"rem": [["!strip_default_pii", "x"]]})
65+
66+
if event.get("user"):
67+
event["user"] = gone()
68+
69+
request = event.get("request")
70+
if request:
71+
if request.get("cookies"):
72+
request["cookies"] = gone()
73+
if request.get("headers"):
74+
headers = request["headers"]
75+
for key in list(headers):
76+
if key.lower().replace("_", "-") in (
77+
"set-cookie",
78+
"cookie",
79+
"authentication",
80+
):
81+
headers[key] = gone()
82+
5583
return event
5684

5785

@@ -63,7 +91,7 @@ def strip_frame(frame):
6391
def strip_databag(obj, remaining_depth=20):
6492
assert not isinstance(obj, bytes), "bytes should have been normalized before"
6593
if remaining_depth <= 0:
66-
return AnnotatedValue(None, {"": {"rem": [["!dep", "x"]]}})
94+
return AnnotatedValue(None, {"rem": [["!dep", "x"]]})
6795
if isinstance(obj, text_type):
6896
return strip_string(obj)
6997
if isinstance(obj, Mapping):

tests/integrations/django/myapp/settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,5 +136,5 @@ def process_response(self, request, response):
136136
STATIC_URL = "/static/"
137137

138138
sentry_sdk.get_current_hub().bind_client(
139-
sentry_sdk.Client(integrations=[DjangoIntegration()])
139+
sentry_sdk.Client(integrations=[DjangoIntegration()], send_default_pii=True)
140140
)

tests/integrations/flask/test_flask.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,15 @@ def test_flask_login_partially_configured(
115115
assert event.get("user", {}).get("id") is None
116116

117117

118+
@pytest.mark.parametrize("send_default_pii", [True, False])
118119
@pytest.mark.parametrize("user_id", [None, "42", 3])
119-
def test_flask_login_configured(sentry_init, app, user_id, capture_events, monkeypatch):
120-
sentry_init(integrations=[flask_sentry.FlaskIntegration()])
120+
def test_flask_login_configured(
121+
send_default_pii, sentry_init, app, user_id, capture_events, monkeypatch
122+
):
123+
sentry_init(
124+
send_default_pii=send_default_pii,
125+
integrations=[flask_sentry.FlaskIntegration()],
126+
)
121127

122128
class User(object):
123129
is_authenticated = is_active = True
@@ -146,7 +152,7 @@ def login():
146152
assert client.get("/message").status_code == 200
147153

148154
event, = events
149-
if user_id is None:
155+
if user_id is None or not send_default_pii:
150156
assert event.get("user", {}).get("id") is None
151157
else:
152158
assert event["user"]["id"] == str(user_id)

0 commit comments

Comments
 (0)