Skip to content

Conversation

philprime
Copy link
Member

@philprime philprime commented Oct 9, 2025

📜 Description

  • Adds a check using the iOS runtime version and the DTXcode from the app's Info.plist to detect if the environment should be considered dangerous for PII.
  • Apps built with Xcode 26 and running on iOS 26 will not start Session Replay due to PII concerns
  • Adds a new option (should be deprecated as soon as fixed) to override the behavior.

💡 Motivation and Context

While working on #6292 I noticed that standard SwiftUI components like Text, Image, Label are not properly masked. Further research has shown that this is caused by the masking/redaction logic not being able to detect sensitive views due to Apple changing the internal rendering logic with their release of Liquid Glass on iOS 26.0.

Liquid Glass is only used by an app running on iOS 26.0 if the app was built with Xcode 26.0, therefore we can rule out apps built with older Xcode versions. This can be checked by looking at the DT* fields in the app's Info.plist.

The approach taken in this PR is defensive, meaning that we assume the runtime environment is dangerous for PII unless there are strong indicators it's safe. This approach should reduce the risk of PII being leaked by changes outside of our control, but it could cause session replay not being started even though it's safe ("better safe than sorry").

I am going to create a follow-up issue with more insight into the issue and link it here afterwards.

💚 How did you test it?

  • I exported a sample app using Xcode 16.4 and using Xcode 26, then compared the Info.plist of the two apps to confirm the values of the field DTXcode. Using Xcode 16.4
image [Info-iOS18.plist.xml](https://github.com/user-attachments/files/22799590/Info-iOS18.plist.xml) [Info-iOS26.plist.xml](https://github.com/user-attachments/files/22799591/Info-iOS26.plist.xml)
  • I ran the iOS-SwiftUI sample using Xcode 16.4 on iOS 26.0 simulator → session replay is enabled
  • I ran the iOS-SwiftUI sample using Xcode 26.0 on iOS 26.0 simulator:
    • with options.sessionReplay.disableInDangerousEnvironment = true (default) → session replay is disabled
    • with options.sessionReplay.disableInDangerousEnvironment = false → session replay was enabled

📝 Checklist

You have to check all boxes before merging:

  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.

Copy link
Member

@philipphofmann philipphofmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for driving this. We still need a changelog entry, and my comments are mostly about the naming of the option.

@philprime philprime force-pushed the philprime/hotfix/disable-session-replay-ios26 branch from e0b8508 to d19908f Compare October 9, 2025 15:26
cursor[bot]

This comment was marked as outdated.

Copy link

codecov bot commented Oct 9, 2025

Codecov Report

❌ Patch coverage is 97.76786% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.803%. Comparing base (3af1ae9) to head (5bdb593).
⚠️ Report is 1 commits behind head on v8.x.

Files with missing lines Patch % Lines
...Replay/SentrySessionReplayEnvironmentChecker.swift 95.698% 4 Missing ⚠️
...wift/Helper/InfoPlist/SentryInfoPlistWrapper.swift 97.560% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@              Coverage Diff              @@
##              v8.x     #6389       +/-   ##
=============================================
+ Coverage   86.701%   86.803%   +0.102%     
=============================================
  Files          437       441        +4     
  Lines        37162     37382      +220     
  Branches     17396     17483       +87     
=============================================
+ Hits         32220     32449      +229     
+ Misses        4897      4888        -9     
  Partials        45        45               
Files with missing lines Coverage Δ
SentryTestUtils/TestInfoPlistWrapper.swift 100.000% <100.000%> (ø)
...estUtils/TestSessionReplayEnvironmentChecker.swift 100.000% <100.000%> (ø)
Sources/Sentry/SentryDependencyContainer.m 89.843% <100.000%> (+0.120%) ⬆️
Sources/Sentry/SentrySessionReplayIntegration.m 87.410% <100.000%> (+0.301%) ⬆️
...tegrations/SessionReplay/SentrySessionReplay.swift 90.965% <100.000%> (+0.411%) ⬆️
Sources/Swift/SentryExperimentalOptions.swift 84.615% <100.000%> (+1.282%) ⬆️
...wift/Helper/InfoPlist/SentryInfoPlistWrapper.swift 97.560% <97.560%> (ø)
...Replay/SentrySessionReplayEnvironmentChecker.swift 95.698% <95.698%> (ø)

... and 10 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 3af1ae9...5bdb593. Read the comment docs.

Copy link
Contributor

github-actions bot commented Oct 9, 2025

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 1219.98 ms 1248.83 ms 28.85 ms
Size 23.75 KiB 991.86 KiB 968.12 KiB

Baseline results on branch: v8.x

Startup times

Revision Plain With Sentry Diff
a7a0a2b 1218.61 ms 1248.69 ms 30.08 ms
f76f6bf 1207.70 ms 1233.27 ms 25.57 ms
c6afcc7 1224.31 ms 1256.22 ms 31.92 ms
3af1ae9 1225.60 ms 1252.65 ms 27.05 ms
5e3fb04 1239.84 ms 1267.39 ms 27.55 ms
b66be9b 1218.22 ms 1244.19 ms 25.96 ms

App size

Revision Plain With Sentry Diff
a7a0a2b 23.75 KiB 996.04 KiB 972.29 KiB
f76f6bf 23.74 KiB 981.30 KiB 957.56 KiB
c6afcc7 23.75 KiB 996.03 KiB 972.28 KiB
3af1ae9 23.74 KiB 981.29 KiB 957.55 KiB
5e3fb04 23.74 KiB 981.30 KiB 957.56 KiB
b66be9b 23.75 KiB 996.03 KiB 972.28 KiB

Previous results on branch: philprime/hotfix/disable-session-replay-ios26

Startup times

Revision Plain With Sentry Diff
7f548c7 1203.63 ms 1240.19 ms 36.56 ms
99fac9e 1218.98 ms 1252.16 ms 33.19 ms
c77274a 1233.69 ms 1264.40 ms 30.70 ms

App size

Revision Plain With Sentry Diff
7f548c7 23.75 KiB 998.22 KiB 974.47 KiB
99fac9e 23.74 KiB 990.99 KiB 967.25 KiB
c77274a 23.75 KiB 998.22 KiB 974.48 KiB

cursor[bot]

This comment was marked as outdated.

@philprime
Copy link
Member Author

philprime commented Oct 10, 2025

From a sync between @philipphofmann and myself on Oct 10th 2025:

  • Our main concern is user PII therefore we prefer to disable session replay in cases where masking is not reliable over session replay being available. This might cause SDK users to question why they are not receiving session replays, but we believe this is in their interest too.
  • We move the options.sessionReplay.enableInUnreliableEnvironment to options.experimental.enableInUnreliableEnvironment
  • The option is there to allow SDK users to overrule our detection of unreliable environment for the case they know it better than us
  • This gives us more time to build a proper API because we want to ship a fix as soon as possible without having to consider all aspects of future-proofing this change (incl. backwards and forwards compatibility)
  • We will remove the option most likely in a future minor version
  • If an SDK user doesn't notice that we disabled session replay in a minor version for them, this can cause disruption. After consideration we did not find a intuitive way without causing too much friction to inform the developer at build time. Therefore we will only add warnings to these:
    • Release Notes
    • Changelog (in v8.x branch and link in v9 branch in main)
    • Troubleshooting Docs
  • We will also add a link to v8 branch + v8 Changelog in the v9/main branch README.md
  • We are going to release this hotfix as 8.57.0 after resetting the v8.x branch to the 8.56.2 commit + cherry-picking CI commits to be able to release the hotfix (@philipphofmann will take care of this).
  • The changes of this PR will also be applied to v9 in a follow-up PR

@philprime philprime self-assigned this Oct 10, 2025
@kahest
Copy link
Member

kahest commented Oct 10, 2025

  • options.experimental.enableInUnreliableEnvironment

I think we should still include SR in the option name, maybe something like options.experimental.enableSessionReplayInUnreliableEnvironment because I assume/suggest we only use this for SR

@kahest
Copy link
Member

kahest commented Oct 10, 2025

  • We are going to release this hotfix as 8.57.0

why not 8.56.3 which would be an actual hotfix rather than a minor bump?

@kahest
Copy link
Member

kahest commented Oct 10, 2025

  • If an SDK user doesn't notice that we disabled session replay in a minor version for them, this can cause disruption. After consideration we did not find a intuitive way without causing too much friction to inform the developer at build time.

because it's not mentioned in your comment - we'll still show a log message right?

@philprime
Copy link
Member Author

philprime commented Oct 10, 2025

I think we should still include SR in the option name, maybe something like options.experimental.enableSessionReplayInUnreliableEnvironment because I assume/suggest we only use this for SR

Fine for me, as it is going to be an experimental option we can reduce the usage scope to session replay. In case we want to repurpose it at some point we should keep the name broader.

  • We are going to release this hotfix as 8.57.0

I would propose we go for a minor because it has quite some impact on the SDK user.

because it's not mentioned in your comment - we'll still show a log message right?

Yes

@philprime philprime marked this pull request as draft October 10, 2025 10:34
@philprime
Copy link
Member Author

@cursor review
@sentry review

cursor[bot]

This comment was marked as outdated.

github-actions bot and others added 3 commits October 10, 2025 14:09
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
(cherry picked from commit 3e57e15)
@philprime philprime force-pushed the philprime/hotfix/disable-session-replay-ios26 branch from 6c22528 to 416889b Compare October 10, 2025 12:12
Copy link
Contributor

🚨 Detected changes in high risk code 🚨

High-risk code can easily blow up and is hard to test. We had severe bugs in the past. Be extra careful when changing these files, and have an extra careful look at these:

  • Sources/Sentry/SentryFileManager.m
  • Sources/Sentry/SentryNetworkTracker.m

Copy link
Contributor

@itaybre itaybre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, but I have some questions

Copy link
Member

@philipphofmann philipphofmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I'm sorry I added plenty of comments. Also some nits. Feel free to ignore some of the nits, if you want to speed the PR up.

cursor[bot]

This comment was marked as outdated.

@philprime
Copy link
Member Author

Based on this PR comment I did an analysis of the LC_BUILD_VERSION and will add it as another check:

# Built with Xcode 26.0 for iOS Simulator 18.6
$ otool -l iOS-SwiftUI | grep -A 7 LC_BUILD_VERSION
      cmd LC_BUILD_VERSION
  cmdsize 32
 platform 7
    minos 14.0
      sdk 18.5
   ntools 1
     tool 3
  version 1167.5
  
# Built with Xcode 26.0 for iOS Simulator 26.0
$ otool -l iOS-SwiftUI | grep -A 7 LC_BUILD_VERSION
      cmd LC_BUILD_VERSION
  cmdsize 32
 platform 7
    minos 14.0
      sdk 18.5
   ntools 1
     tool 3
  version 1167.5

# Built with Xcode 26.0 for iOS Simulator 18.6
$ otool -l iOS-SwiftUI | grep -A 7 LC_BUILD_VERSION
      cmd LC_BUILD_VERSION
  cmdsize 32
 platform 7
    minos 14.0
      sdk 26.0
   ntools 1
     tool 3
  version 1221.4

# Built with Xcode 26.0 for iOS Simulator 26.0
$ otool -l iOS-SwiftUI | grep -A 7 LC_BUILD_VERSION
      cmd LC_BUILD_VERSION
  cmdsize 32
 platform 7
    minos 14.0
      sdk 26.0
   ntools 1
     tool 3
  version 1221.4

Copy link
Member

@philipphofmann philipphofmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, when resolving the comment about the public enum SentryInfoPlistKey

#6389 (comment)

@philprime
Copy link
Member Author

As mentioned in this PR comment we should not use _dyld_get_image_header(0) on the main thread because we already had to fix app hangs with #6181.

Therefore I am going to remove it from the PR now.

…ive-C usage

- Changed the default initializer to override and set the bundle to Bundle.main.
- Added a new public initializer to allow custom bundle injection while maintaining compatibility with Objective-C.
@philprime philprime enabled auto-merge (squash) October 14, 2025 09:06
@philprime philprime merged commit ab82dac into v8.x Oct 14, 2025
254 of 262 checks passed
@philprime philprime deleted the philprime/hotfix/disable-session-replay-ios26 branch October 14, 2025 09:53
philprime added a commit that referenced this pull request Oct 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants