Overview › Security
Security
Cert pinning + Keychain + passkey; ATS exceptions in Notification Extension are concerning.
70
SCORE
Summary
Strong baseline: cert pinning, Keychain wrappers, NokNok passkey, ThreatMetrix device intelligence, SecRandomCopyBytes for nonces. Concerning gaps: NSAllowsArbitraryLoads = true in Notification Service Extension Info.plist (production AND QA), unverified Privacy Manifest, print() statements that may leak PII.
Security controls matrix
| Control | Status | Evidence |
|---|---|---|
| HTTPS-only | PARTIAL | Main app yes; NSE has NSAllowsArbitraryLoads = true |
| Cert pinning | PRESENT | CostcoServerTrustManager |
| Keychain | PRESENT | Storage SPM + Keychain wrappers |
| Passkey (FIDO2) | PRESENT | NokNok PasskeyManagerKit |
| Device risk | PRESENT | ThreatMetrixKit |
| SecRandomCopyBytes | PRESENT | OIDCAuthenticationHelper |
| App Privacy Manifest | VERIFY | Required for SDKs accessing Required Reason APIs |
| Jailbreak detection | ABSENT | Compare with Android Play Integrity |
| Screen capture block | ABSENT | Sensitive screens (DMC, payment) should hide on backgrounding |
| Insecure logging (print) | REVIEW | 30+ print() calls — audit for PII |
Findings
CRITICAL
NSAllowsArbitraryLoads = true in Notification Service Extension
Both Costco/NotificationServiceExtension/NotificationServiceExtension-Info.plist and the QA Info.plist have
NSAllowsArbitraryLoads = true. This bypasses ATS for the entire NSE process.Recommendation: Replace with
NSExceptionDomains for the specific hosts the NSE needs (typically image CDN). Remove the broad allow.HIGH
Privacy Manifest required since 2024
Apple requires
PrivacyInfo.xcprivacy for apps and SDKs accessing Required Reason APIs (UserDefaults, FileManager, etc.). Without it, App Review will reject submissions.Recommendation: Generate
PrivacyInfo.xcprivacy covering this app's data collection + Required Reason API usage; verify all third-party SDKs ship one.HIGH
No FLAG_SECURE-equivalent on sensitive screens
Payment / DMC / passkey screens should hide content when the app is backgrounded (snapshot in app switcher).
Recommendation: Override
application(_:willResignActive:) to show a privacy overlay; restore on didBecomeActive. For SwiftUI use a scenePhase observer.MEDIUM
print() may leak PII
30+
print() calls observed. print() writes regardless of build configuration; if any logs membership ID, email, etc., they end up in device logs accessible to other apps with diagnostic entitlements.Recommendation: Adopt
os.Logger with the privacy: .private argument for sensitive interpolations; audit and replace existing print calls.Findings in this category
Costco iOS · Code Review Report · Generated 2026-05-07 · 88 machine-curated findings