Skip to content

Commit 8293c19

Browse files
committed
1 parent 251e27d commit 8293c19

File tree

3 files changed

+125
-0
lines changed

3 files changed

+125
-0
lines changed

sentry_sdk/client.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
from sentry_sdk.sessions import SessionFlusher
3030
from sentry_sdk.envelope import Envelope
3131
from sentry_sdk.profiler import has_profiling_enabled, setup_profiler
32+
from sentry_sdk.scrubber import EventScrubber
3233

3334
from sentry_sdk._types import TYPE_CHECKING
3435

@@ -111,6 +112,9 @@ def _get_options(*args, **kwargs):
111112
if rv["enable_tracing"] is True and rv["traces_sample_rate"] is None:
112113
rv["traces_sample_rate"] = 1.0
113114

115+
if rv["event_scrubber"] is None:
116+
rv["event_scrubber"] = EventScrubber()
117+
114118
return rv
115119

116120

@@ -249,6 +253,11 @@ def _prepare_event(
249253
self.options["project_root"],
250254
)
251255

256+
if event is not None:
257+
event_scrubber = self.options["event_scrubber"]
258+
if event_scrubber and not self.options["send_default_pii"]:
259+
event_scrubber.scrub_event(event)
260+
252261
# Postprocess the event here so that annotated types do
253262
# generally not surface in before_send
254263
if event is not None:

sentry_sdk/consts.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ def __init__(
133133
trace_propagation_targets=[ # noqa: B006
134134
MATCH_ALL
135135
], # type: Optional[Sequence[str]]
136+
event_scrubber=None, # type: Optional[sentry_sdk.scrubber.EventScrubber]
136137
):
137138
# type: (...) -> None
138139
pass

sentry_sdk/scrubber.py

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
from sentry_sdk.utils import (
2+
capture_internal_exceptions,
3+
AnnotatedValue,
4+
iter_event_frames,
5+
)
6+
from sentry_sdk._compat import string_types
7+
from sentry_sdk._types import TYPE_CHECKING
8+
9+
if TYPE_CHECKING:
10+
from sentry_sdk._types import Event
11+
from typing import Any
12+
from typing import Dict
13+
from typing import List
14+
from typing import Optional
15+
16+
17+
DEFAULT_DENYLIST = [
18+
# stolen from relay
19+
"password",
20+
"passwd",
21+
"secret",
22+
"api_key",
23+
"apikey",
24+
"auth",
25+
"credentials",
26+
"mysql_pwd",
27+
"privatekey",
28+
"private_key",
29+
"token",
30+
"ip_address",
31+
# django
32+
"csrftoken",
33+
"sessionid",
34+
# wsgi
35+
"remote_addr",
36+
"http_x_csrftoken",
37+
"http_x_forwarded_for",
38+
"http_set_cookie",
39+
"http_cookie",
40+
"http_authorization",
41+
"http_x_api_key",
42+
"http_x_forwarded_for",
43+
"http_x_real_ip",
44+
]
45+
46+
47+
class EventScrubber(object):
48+
def __init__(self, denylist=None):
49+
# type: (Optional[List[str]]) -> None
50+
self.denylist = DEFAULT_DENYLIST if denylist is None else denylist
51+
52+
def scrub_dict(self, d):
53+
# type: (Dict[str, Any]) -> None
54+
if not isinstance(d, dict):
55+
return
56+
57+
for k in d.keys():
58+
if isinstance(k, string_types) and k.lower() in self.denylist:
59+
d[k] = AnnotatedValue.substituted_because_contains_sensitive_data()
60+
61+
def scrub_request(self, event):
62+
# type: (Event) -> None
63+
with capture_internal_exceptions():
64+
if "request" in event:
65+
if "headers" in event["request"]:
66+
self.scrub_dict(event["request"]["headers"])
67+
if "cookies" in event["request"]:
68+
self.scrub_dict(event["request"]["cookies"])
69+
if "data" in event["request"]:
70+
self.scrub_dict(event["request"]["data"])
71+
72+
def scrub_extra(self, event):
73+
# type: (Event) -> None
74+
with capture_internal_exceptions():
75+
if "extra" in event:
76+
self.scrub_dict(event["extra"])
77+
78+
def scrub_user(self, event):
79+
# type: (Event) -> None
80+
with capture_internal_exceptions():
81+
if "user" in event:
82+
self.scrub_dict(event["user"])
83+
84+
def scrub_breadcrumbs(self, event):
85+
# type: (Event) -> None
86+
with capture_internal_exceptions():
87+
if "breadcrumbs" in event:
88+
if "values" in event["breadcrumbs"]:
89+
for value in event["breadcrumbs"]["values"]:
90+
if "data" in value:
91+
self.scrub_dict(value["data"])
92+
93+
def scrub_frames(self, event):
94+
# type: (Event) -> None
95+
with capture_internal_exceptions():
96+
for frame in iter_event_frames(event):
97+
if "vars" in frame:
98+
self.scrub_dict(frame["vars"])
99+
100+
def scrub_spans(self, event):
101+
# type: (Event) -> None
102+
with capture_internal_exceptions():
103+
if "spans" in event:
104+
for span in event["spans"]:
105+
if "data" in span:
106+
self.scrub_dict(span["data"])
107+
108+
def scrub_event(self, event):
109+
# type: (Event) -> None
110+
self.scrub_request(event)
111+
self.scrub_extra(event)
112+
self.scrub_user(event)
113+
self.scrub_breadcrumbs(event)
114+
self.scrub_frames(event)
115+
self.scrub_spans(event)

0 commit comments

Comments
 (0)