Describe the bug
DeviceAccessManager.advertisingIdentifier() force-bridges ASIdentifierManager.shared().advertisingIdentifier into a non-optional Swift UUID:
// PrebidMobile/Swift/PrebidMobileRendering/Utilities/DeviceAccessManager.swift:85
@objc public func advertisingIdentifier() -> String {
ASIdentifierManager.shared().advertisingIdentifier.uuidString
}
Apple annotates -[ASIdentifierManager advertisingIdentifier] as nonnull, so it bridges to a non-optional UUID in Swift. But in rare device states the ObjC property returns nil (the identifier is fetched over XPC from a system daemon that can be unavailable — e.g. very early in launch before the AdSupport service is ready, just after boot / before first unlock, under memory pressure / XPC failure, or under certain MDM / Screen Time restrictions). When it returns nil, the implicit NSUUID? -> UUID bridge calls UUID._unconditionallyBridgeFromObjectiveC, which traps -> EXC_BREAKPOINT and the app crashes.
Note: normal ATT denial / notDetermined does NOT cause this — that returns the all-zeros UUID (00000000-0000-0000-0000-000000000000), which bridges fine. The crash is specifically the nil case, where the OS returns nil despite the nonnull annotation.
This is hit whenever a bid request is built with Targeting.shared.isAllowedAccessDeviceData == true (PBMDeviceInfoParameterBuilder.m:88 reads deviceAccessManager.advertisingIdentifier), so any fetchDemand() call can crash.
To Reproduce
Steps to reproduce the behavior:
- Force ASIdentifierManager.shared().advertisingIdentifier to return nil (e.g. swizzle the getter for testing).
- Ensure Targeting.shared.isAllowedAccessDeviceData returns true.
- Trigger a bid request via BannerAdUnit.fetchDemand(...).
- See error - app crashes with EXC_BREAKPOINT in DeviceAccessManager.advertisingIdentifier() at DeviceAccessManager.swift:85.
Expected behavior
The SDK should tolerate a nil advertising identifier (fall back to an empty string / omit the ifa param) instead of trapping. Suggested fix - treat the value as optional:
@objc public func advertisingIdentifier() -> String {
ASIdentifierManager.shared().advertisingIdentifier?.uuidString ?? ""
}
Screenshots
Symbolicated crash stack (abridged):
Crashed: com.apple.main-thread
0 Foundation UUID._unconditionallyBridgeFromObjectiveC + 196
1 PrebidMobile DeviceAccessManager.advertisingIdentifier() (DeviceAccessManager.swift:85)
2 PrebidMobile -[PBMDeviceInfoParameterBuilder buildBidRequest:] (PBMDeviceInfoParameterBuilder.m:88)
3 PrebidMobile +[PBMParameterBuilderService buildParamsDictWithAdConfiguration:...]
5 PrebidMobile -[PBMBidRequester_Objc getRTBRequest] (PBMBidRequester.m:180)
6 PrebidMobile -[PBMBidRequester_Objc makeRequestWithCompletion:] (PBMBidRequester.m:75)
9 PrebidMobile UserAgentService.fetchUserAgent(completion:) (UserAgentService.swift:37)
11 PrebidMobile -[PBMBidRequester_Objc requestBidsWithCompletion:] (PBMBidRequester.m:55)
12 PrebidMobile AdUnit.baseFetchDemand(adObject:completion:) (AdUnit.swift:182)
13 PrebidMobile AdUnit.fetchDemand(completionBidInfo:) (AdUnit.swift:113)
14 <app> BannerAdUnit.fetchDemand { ... }
Desktop (please complete the following information):
- OS: N/A (iOS SDK issue, not desktop)
- Browser: N/A
- Version: N/A
Smartphone (please complete the following information):
- Device: Multiple (47 distinct devices affected in production)
- OS: iOS (observed on iOS 18.7)
- Browser: N/A (native app, in-app ad rendering)
- Version: PrebidMobile 3.3.1 (same unguarded code also present on master)
Additional context
Low but persistent volume in our production Crashlytics - 50 occurrences across 47 devices (0.6% of crashing users). The root cause is entirely inside the SDK: apps cannot prevent ASIdentifierManager from returning nil (it comes from a system daemon being momentarily unavailable), so this can only be fixed upstream by making the bridge nil-safe.
Describe the bug
DeviceAccessManager.advertisingIdentifier() force-bridges ASIdentifierManager.shared().advertisingIdentifier into a non-optional Swift UUID:
Apple annotates -[ASIdentifierManager advertisingIdentifier] as nonnull, so it bridges to a non-optional UUID in Swift. But in rare device states the ObjC property returns nil (the identifier is fetched over XPC from a system daemon that can be unavailable — e.g. very early in launch before the AdSupport service is ready, just after boot / before first unlock, under memory pressure / XPC failure, or under certain MDM / Screen Time restrictions). When it returns nil, the implicit NSUUID? -> UUID bridge calls UUID._unconditionallyBridgeFromObjectiveC, which traps -> EXC_BREAKPOINT and the app crashes.
Note: normal ATT denial / notDetermined does NOT cause this — that returns the all-zeros UUID (00000000-0000-0000-0000-000000000000), which bridges fine. The crash is specifically the nil case, where the OS returns nil despite the nonnull annotation.
This is hit whenever a bid request is built with Targeting.shared.isAllowedAccessDeviceData == true (PBMDeviceInfoParameterBuilder.m:88 reads deviceAccessManager.advertisingIdentifier), so any fetchDemand() call can crash.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
The SDK should tolerate a nil advertising identifier (fall back to an empty string / omit the ifa param) instead of trapping. Suggested fix - treat the value as optional:
Screenshots
Symbolicated crash stack (abridged):
Desktop (please complete the following information):
Smartphone (please complete the following information):
Additional context
Low but persistent volume in our production Crashlytics - 50 occurrences across 47 devices (0.6% of crashing users). The root cause is entirely inside the SDK: apps cannot prevent ASIdentifierManager from returning nil (it comes from a system daemon being momentarily unavailable), so this can only be fixed upstream by making the bridge nil-safe.