5.6 KiB
| name | description |
|---|---|
| privacy-manifest | Add and check Apple privacy manifests (PrivacyInfo.xcprivacy) for an iOS app or game - required-reason API categories (UserDefaults, file timestamps, system boot time, disk space, active keyboards) with approved reason codes, tracking flag and domains, collected data types, and third-party SDK manifests (ad networks, analytics, Firebase, Unity, Capacitor plugins). Use when App Store Connect sends ITMS-91053 "Missing API declaration" or ITMS-91061 "Missing privacy manifest", or before submitting an iOS build. |
Privacy manifest (iOS)
storebound scan runs the same checks as part of its report (no manifest, undeclared required-reason APIs, SDKs older than their first manifest version) and proposes NSPrivacyTracking and the collected data types from the detected SDKs.
Scan: storebound privacy-manifest --ios ios/App (local, no credentials; --propose prints the app manifest
storebound proposes). Capacitor / Cordova / React Native plugins
live outside the iOS folder; they are found the way Node resolves them: the dependencies of the app's package.json
(next to capacitor.config) in the node_modules there and in every folder above it up to the repo root (so a monorepo's
apps/native/node_modules works), workspace packages (package.json workspaces, Bun / npm / yarn), local SwiftPM
packages (Capacitor 8's CapApp-SPM Package.swift), Pods and SwiftPM checkouts. --sdk-dirs a,b adds folders it
cannot find. Exit 1 when something blocks upload.
What Apple checks at upload
- ITMS-91064 Invalid tracking information: "ITMS-91064: Invalid tracking information - A PrivacyInfo.xcprivacy file contains invalid tracking information at the following path: "PrivacyInfo.xcprivacy". NSPrivacyTracking must be true if NSPrivacyTrackingDomains isn't empty. Keys and values in your app's privacy manifests must be valid." Raised for
true with an empty list as well as for domains with false, in the app's manifest or any SDK's.
storebound apple uploadchecks every manifest in the IPA (app root, Frameworks, bundles; XML or binary) before sending it,apple buildafter the export,check/scan/privacy-manifestin the project. - ITMS-91053 Missing API declaration: the binary uses a required-reason API and no manifest in the app or in the SDK that calls it declares the category with a reason.
- ITMS-91061 Missing privacy manifest: an SDK from Apple's list of commonly used SDKs (Firebase, Google utilities, Alamofire, OneSignal, Unity framework, Capacitor, Flutter ...) is linked without its own manifest (and signature for binary SDKs). Fix by updating the SDK, not by declaring it in your app's manifest.
Steps
- Xcode > File > New > File > App Privacy (PrivacyInfo.xcprivacy), target = the app.
- Run the scan. For each used category add
NSPrivacyAccessedAPITypes> item withNSPrivacyAccessedAPITypeandNSPrivacyAccessedAPITypeReasons. Typical for apps and games:NSPrivacyAccessedAPICategoryUserDefaults+CA92.1(settings / saves read and written by the app itself; Capacitor Preferences and most engines use UserDefaults)NSPrivacyAccessedAPICategoryFileTimestamp+C617.1(timestamps of files in the app container)NSPrivacyAccessedAPICategorySystemBootTime+35F9.1(elapsed time between events)NSPrivacyAccessedAPICategoryDiskSpace+E174.1(check space before writing) Pick the reason that is true; read Apple's reason list ("Describing use of required reason API") if unsure.
- Tracking (ITMS-91064): in every manifest
NSPrivacyTrackingandNSPrivacyTrackingDomainsmust agree: true needs a non-empty list of the domains the code of THAT bundle sends tracking data to, and a non-empty list needs true. When the tracking comes from an SDK (ad network, mediation such as LevelPlay / AppLovin MAX / AdMob, attribution), the SDK's own manifest declares it and the app's manifest says false, while App Privacy in App Store Connect still says "used for tracking" and the ATT prompt stays (store-declarations). Never set the app's manifest to true with an empty list: Apple refuses the build as Invalid Binary a minute after the upload. Only when the app's own code tracks, list its domains inappPrivacy.trackingDomains;storebound privacy-manifest --ios ios/App --proposeprints the manifest with true only then. NSPrivacyCollectedDataTypes: what the app itself collects; SDK manifests cover their own collection. Xcode's Privacy Report (Product > Archive > Generate Privacy Report) merges all manifests; compare it with App Privacy.- SDKs flagged "ships no PrivacyInfo.xcprivacy": update to a version that has one (ad networks and mediation
adapters added manifests in 2024 releases; see
ads-mediation-checksfor adapter / SDK version pairs). - Re-run the scan, archive, upload; Apple's email lists any remaining ITMS-910xx issue per framework.
Gotchas
- The scan is a text search: it can miss calls inside binary frameworks (their manifest must cover them) and flag a harmless symbol name; confirm before adding a category you do not use.
- A manifest must be in the app target's Copy Bundle Resources, not only in the project.
checksaying "tracking declared by the manifest" (info) is the correct setup for SDK tracking; a warning that no manifest declares tracking means: check the SDK version ships its manifest (pod install, resolve packages), not "set the app's manifest to true".- Static libraries cannot carry a manifest bundle by themselves; the vendor ships a resource bundle or you merge their declarations into the app's manifest as their docs say.