diff --git a/CHANGELOG.md b/CHANGELOG.md index b5233eabb0..d35306acac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ ### Features +- Expose the iOS `enableMemoryIntrospection` option to omit memory contents from native crash reports ([#6547](https://github.com/getsentry/sentry-react-native/pull/6674)) - Add `anrProfilingSampleRate` option to profile ANRs on Android ([#6673](https://github.com/getsentry/sentry-react-native/pull/6673)) ### Dependencies diff --git a/packages/core/RNSentryCocoaTester/RNSentryCocoaTesterTests/RNSentryStartTests.swift b/packages/core/RNSentryCocoaTester/RNSentryCocoaTesterTests/RNSentryStartTests.swift index 682c651936..0bcd75dac7 100644 --- a/packages/core/RNSentryCocoaTester/RNSentryCocoaTesterTests/RNSentryStartTests.swift +++ b/packages/core/RNSentryCocoaTester/RNSentryCocoaTesterTests/RNSentryStartTests.swift @@ -226,6 +226,25 @@ final class RNSentryStartTests: XCTestCase { XCTAssertTrue(actualOptions.screenshot.maskAllImages) } + func testMemoryIntrospectionOption() throws { + try startFromRN(options: [ + "dsn": "https://abcd@efgh.ingest.sentry.io/123456", + "enableMemoryIntrospection": true + ]) + + let actualOptions = SentrySDK.internal.options + XCTAssertTrue(actualOptions.enableMemoryIntrospection) + } + + func testMemoryIntrospectionOptionDefault() throws { + try startFromRN(options: [ + "dsn": "https://abcd@efgh.ingest.sentry.io/123456" + ]) + + let actualOptions = SentrySDK.internal.options + XCTAssertFalse(actualOptions.enableMemoryIntrospection) + } + func startFromRN(options: [String: Any]) throws { var error: NSError? RNSentryStart.start(options: options, error: &error) diff --git a/packages/core/src/js/options.ts b/packages/core/src/js/options.ts index 6b59decd06..651ad68ede 100644 --- a/packages/core/src/js/options.ts +++ b/packages/core/src/js/options.ts @@ -252,6 +252,21 @@ export interface BaseReactNativeOptions { */ enableMetricKit?: boolean; + /** + * When enabled, `SentryCrash` reads memory near the crash site while capturing a native crash + * (e.g. `EXC_BAD_ACCESS`) and embeds string-based stack contents in the event. This can help + * with debugging, but may also expose sensitive information (such as user IDs or personal data), + * which can even surface in the issue title. + * + * Disable this option to keep native crash reporting while omitting memory contents. + * + * iOS only + * + * @default false + * @platform ios + */ + enableMemoryIntrospection?: boolean; + /** * The max queue size for capping the number of envelopes waiting to be sent by Transport. */ diff --git a/packages/core/test/wrapper.test.ts b/packages/core/test/wrapper.test.ts index c98a7527e4..ca86f409b2 100644 --- a/packages/core/test/wrapper.test.ts +++ b/packages/core/test/wrapper.test.ts @@ -353,6 +353,41 @@ describe('Tests Native Wrapper', () => { expect(NATIVE.enableNative).toBe(true); }); + test('passes enableMemoryIntrospection to the Native SDK when set', async () => { + await NATIVE.initNativeSdk({ + dsn: VALID_DSN, + enableNative: true, + autoInitializeNativeSdk: true, + enableMemoryIntrospection: true, + devServerUrl: undefined, + defaultSidecarUrl: undefined, + mobileReplayOptions: undefined, + }); + + expect(RNSentry.initNativeSdk).toHaveBeenCalled(); + // @ts-expect-error mock value + const initParameter = RNSentry.initNativeSdk.mock.calls[0][0]; + expect(initParameter).toEqual(expect.objectContaining({ enableMemoryIntrospection: true })); + expect(NATIVE.enableNative).toBe(true); + }); + + test('does not pass enableMemoryIntrospection to the Native SDK when not set', async () => { + await NATIVE.initNativeSdk({ + dsn: VALID_DSN, + enableNative: true, + autoInitializeNativeSdk: true, + devServerUrl: undefined, + defaultSidecarUrl: undefined, + mobileReplayOptions: undefined, + }); + + expect(RNSentry.initNativeSdk).toHaveBeenCalled(); + // @ts-expect-error mock value + const initParameter = RNSentry.initNativeSdk.mock.calls[0][0]; + expect(initParameter).not.toHaveProperty('enableMemoryIntrospection'); + expect(NATIVE.enableNative).toBe(true); + }); + test('does not initialize with autoInitializeNativeSdk: false', async () => { NATIVE.enableNative = false; debug.warn = jest.fn();