sentry_sdk.scrubber
from sentry_sdk.utils import ( capture_internal_exceptions, AnnotatedValue, iter_event_frames, ) from typing import TYPE_CHECKING, cast, List, Dict if TYPE_CHECKING: from sentry_sdk._types import Event from typing import Optional DEFAULT_DENYLIST = [ # stolen from relay "password", "passwd", "secret", "api_key", "apikey", "auth", "credentials", "mysql_pwd", "privatekey", "private_key", "token", "session", # django "csrftoken", "sessionid", # wsgi "x_csrftoken", "x_forwarded_for", "set_cookie", "cookie", "authorization", "x_api_key", # other common names used in the wild "aiohttp_session", # aiohttp "connect.sid", # Express "csrf_token", # Pyramid "csrf", # (this is a cookie name used in accepted answers on stack overflow) "_csrf", # Express "_csrf_token", # Bottle "PHPSESSID", # PHP "_session", # Sanic "symfony", # Symfony "user_session", # Vue "_xsrf", # Tornado "XSRF-TOKEN", # Angular, Laravel ] DEFAULT_PII_DENYLIST = [ "x_forwarded_for", "x_real_ip", "ip_address", "remote_addr", ] class EventScrubber: def __init__( self, denylist: "Optional[List[str]]" = None, recursive: bool = False, send_default_pii: bool = False, pii_denylist: "Optional[List[str]]" = None, ) -> None: """ A scrubber that goes through the event payload and removes sensitive data configured through denylists. :param denylist: A security denylist that is always scrubbed, defaults to DEFAULT_DENYLIST. :param recursive: Whether to scrub the event payload recursively, default False. :param send_default_pii: Whether pii is sending is on, pii fields are not scrubbed. :param pii_denylist: The denylist to use for scrubbing when pii is not sent, defaults to DEFAULT_PII_DENYLIST. """ self.denylist = DEFAULT_DENYLIST.copy() if denylist is None else denylist if not send_default_pii: pii_denylist = ( DEFAULT_PII_DENYLIST.copy() if pii_denylist is None else pii_denylist ) self.denylist += pii_denylist self.denylist = [x.lower() for x in self.denylist] self.recursive = recursive def scrub_list(self, lst: object) -> None: """ If a list is passed to this method, the method recursively searches the list and any nested lists for any dictionaries. The method calls scrub_dict on all dictionaries it finds. If the parameter passed to this method is not a list, the method does nothing. """ if not isinstance(lst, list): return for v in lst: self.scrub_dict(v) # no-op unless v is a dict self.scrub_list(v) # no-op unless v is a list