Repository: getsentry/sentry

Issue:
SDK Crash Detection: Define an allow list for stack traces
Define an allow list for which frames the feature can keep cause the current logic doesn't guarantee accidentally collecting irrelevant frames from customers.

https://github.com/getsentry/sentry/blob/ea6b6dc281a0a833cd58f4ff2e8274e26ee9e654/src/sentry/utils/sdk_crashes/event_stripper.py#L122-L132

We only keep SDK frames and system library frames, which we detect based on the `code_file` path as described here https://github.com/getsentry/sentry/issues/51023.


Discussion:

Resolving patch:
diff --git a/fixtures/sdk_crash_detection/crash_event.py b/fixtures/sdk_crash_detection/crash_event.py
--- a/fixtures/sdk_crash_detection/crash_event.py
+++ b/fixtures/sdk_crash_detection/crash_event.py
@@ -18,7 +18,7 @@
 def get_sentry_frame(function: str, in_app: bool = False) -> Mapping[str, Any]:
     return {
         "function": function,
-        "package": "Sentry",
+        "package": "/private/var/containers/Bundle/Application/59E988EF-46DB-4C75-8E08-10C27DC3E90E/iOS-Swift.app/Frameworks/Sentry.framework/Sentry",
         "in_app": in_app,
         "image_addr": "0x100304000",
     }
diff --git a/src/sentry/utils/sdk_crashes/event_stripper.py b/src/sentry/utils/sdk_crashes/event_stripper.py
--- a/src/sentry/utils/sdk_crashes/event_stripper.py
+++ b/src/sentry/utils/sdk_crashes/event_stripper.py
@@ -147,10 +147,23 @@ def _strip_frames(
     frames: Sequence[Mapping[str, Any]], sdk_crash_detector: SDKCrashDetector
 ) -> Sequence[Mapping[str, Any]]:
     """
-    Only keep SDK frames or non in app frames.
+    Only keep SDK frames or Apple system libraries.
+    We need to adapt this logic once we support other platforms.
     """
+
+    def is_system_library(frame: Mapping[str, Any]) -> bool:
+        fields_containing_paths = {"package", "module", "abs_path"}
+        system_library_paths = {"/System/Library/", "/usr/lib/system/"}
+
+        for field in fields_containing_paths:
+            for path in system_library_paths:
+                if frame.get(field, "").startswith(path):
+                    return True
+
+        return False
+
     return [
         frame
         for frame in frames
-        if sdk_crash_detector.is_sdk_frame(frame) or frame.get("in_app", None) is False
+        if sdk_crash_detector.is_sdk_frame(frame) or is_system_library(frame)
     ]
diff --git a/src/sentry/utils/sdk_crashes/sdk_crash_detection.py b/src/sentry/utils/sdk_crashes/sdk_crash_detection.py
--- a/src/sentry/utils/sdk_crashes/sdk_crash_detection.py
+++ b/src/sentry/utils/sdk_crashes/sdk_crash_detection.py
@@ -54,7 +54,6 @@ def detect_sdk_crash(self, event: Event, event_project_id: int) -> Optional[Even
             return None
 
         if self.cocoa_sdk_crash_detector.is_sdk_crash(frames):
-            # We still need to strip event data for to avoid collecting PII. We will do this in a separate PR.
             sdk_crash_event_data = strip_event_data(event.data, self.cocoa_sdk_crash_detector)
 
             set_path(


Test patch:
diff --git a/tests/sentry/utils/sdk_crashes/test_event_stripper.py b/tests/sentry/utils/sdk_crashes/test_event_stripper.py
--- a/tests/sentry/utils/sdk_crashes/test_event_stripper.py
+++ b/tests/sentry/utils/sdk_crashes/test_event_stripper.py
@@ -1,7 +1,6 @@
 import abc
 
 from fixtures.sdk_crash_detection.crash_event import (
-    IN_APP_FRAME,
     get_crash_event,
     get_crash_event_with_frames,
     get_frames,
@@ -190,16 +189,28 @@ def test_strip_event_data_keeps_exception_stacktrace(self):
             "platform": "platform",
         }
 
-    def test_strip_frames_sentry_in_app_frame_kept(self):
-        frames = get_frames("SentryCrashMonitor_CPPException.cpp", sentry_frame_in_app=True)
-        self._execute_strip_frames_test(frames)
-
-    def test_strip_frames_sentry_non_in_app_frame_kept(self):
+    def test_strip_frames(self):
         frames = get_frames("SentryCrashMonitor_CPPException.cpp", sentry_frame_in_app=False)
-        self._execute_strip_frames_test(frames)
 
-    def _execute_strip_frames_test(self, frames):
-        event_data = get_crash_event_with_frames(frames)
+        frames_kept = [
+            {
+                "abs_path": "/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore",
+            },
+            {
+                "module": "/usr/lib/system/libsystem_c.dylib",
+            },
+        ]
+
+        frames_stripped = [
+            {
+                "abs_path": "/System/Librry/PrivateFrameworks/UIKitCore.framework/UIKitCore",
+            },
+            {
+                "module": "a/usr/lib/system/libsystem_c.dylib",
+            },
+        ]
+
+        event_data = get_crash_event_with_frames(frames_kept + frames_stripped + list(frames))
 
         event = self.create_event(
             data=event_data,
@@ -212,17 +223,15 @@ def _execute_strip_frames_test(self, frames):
             stripped_event_data, "exception", "values", -1, "stacktrace", "frames"
         )
 
-        assert len(stripped_frames) == 7
-        assert (
-            len(
-                [
-                    frame
-                    for frame in stripped_frames
-                    if frame["function"] == IN_APP_FRAME["function"]
-                ]
-            )
-            == 0
-        ), "in_app frame should be removed"
+        assert len(stripped_frames) == 9
+
+        cocoa_sdk_frame = stripped_frames[-1]
+        assert cocoa_sdk_frame == {
+            "function": "SentryCrashMonitor_CPPException.cpp",
+            "package": "/private/var/containers/Bundle/Application/59E988EF-46DB-4C75-8E08-10C27DC3E90E/iOS-Swift.app/Frameworks/Sentry.framework/Sentry",
+            "in_app": False,
+            "image_addr": "0x100304000",
+        }
 
 
 @region_silo_test