-
Notifications
You must be signed in to change notification settings - Fork 675
Scrub nested secrets with the default event scrubber #7624
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| import copy | ||
| from typing import TYPE_CHECKING, Dict, List, cast | ||
|
|
||
| from sentry_sdk.utils import ( | ||
|
|
@@ -111,12 +112,17 @@ def scrub_dict(self, d: object) -> None: | |
| if not isinstance(d, dict): | ||
| return | ||
|
|
||
| for k, v in d.items(): | ||
| for k, v in list(d.items()): | ||
| # The cast is needed because mypy is not smart enough to figure out that k must be a | ||
| # string after the isinstance check. | ||
| if isinstance(k, str) and k.lower() in self.denylist: | ||
| d[k] = AnnotatedValue.substituted_because_contains_sensitive_data() | ||
| elif self.recursive: | ||
| # Nested containers are often the caller's objects. Copy before | ||
| # walking them so scrubbing the event does not change that data. | ||
| if isinstance(v, (dict, list)): | ||
| v = copy.deepcopy(v) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think it's wise to start copying every event |
||
| d[k] = v | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Deepcopy can skip remaining secretsMedium Severity
Reviewed by Cursor Bugbot for commit ac1726e. Configure here. |
||
| self.scrub_dict(v) # no-op unless v is a dict | ||
| self.scrub_list(v) # no-op unless v is a list | ||
|
|
||
|
|
@@ -164,8 +170,18 @@ def scrub_spans(self, event: "Event") -> None: | |
| with capture_internal_exceptions(): | ||
| if "spans" in event: | ||
| for span in cast(List[Dict[str, object]], event["spans"]): | ||
| if "data" in span: | ||
| self.scrub_dict(span["data"]) | ||
| data = span.get("data") | ||
| if not isinstance(data, dict): | ||
| continue | ||
| # PyMongo stores a logical session id here. "session" is on the | ||
| # denylist because of cookies, and this value is not a secret. | ||
| op_ids = data.get("operation_ids") | ||
| session = op_ids.get("session") if isinstance(op_ids, dict) else None | ||
| self.scrub_dict(data) | ||
| if session is not None: | ||
| restored = data.get("operation_ids") | ||
| if isinstance(restored, dict): | ||
| restored["session"] = session | ||
|
|
||
| def scrub_event(self, event: "Event") -> None: | ||
| self.scrub_request(event) | ||
|
|
||


Uh oh!
There was an error while loading. Please reload this page.