# iOS Privacy Manifest (PrivacyInfo.xcprivacy) present and complete

- **Pattern:** `ab-000464` (`app-store-privacy-data.privacy-declarations.no-privacy-manifest`)
- **Severity:** critical
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000464
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000464)

## Why it matters

Apple has required PrivacyInfo.xcprivacy for all iOS app updates since May 1, 2024. A missing or incomplete manifest means Apple's automated binary validation rejects your upload before a human reviewer ever sees it. Beyond the submission block, an incomplete manifest misrepresents your app's data practices to users and regulators — violating GDPR Art.5(1)(c) data-minimisation transparency and CCPA §1798.100 disclosure requirements. If your app or any of its third-party pods uses Required Reason APIs (UserDefaults, FileManager, SystemBootTime, DiskSpace) without declaring them, every update you ship is an unverifiable compliance gap.

## Severity rationale

Critical because a missing or incomplete PrivacyInfo.xcprivacy causes binary rejection on every iOS submission — there is no workaround or grace period.

## Remediation

Create `ios/[AppName]/PrivacyInfo.xcprivacy` as a property list and declare all four required keys. For Expo managed workflow, add the `privacyManifests` key in your app config plugin or install `expo-privacy-manifests`. After updating, run:

```bash
find ios/ -name PrivacyInfo.xcprivacy
```

to enumerate manifests from your own code and all CocoaPods. Then use Xcode's Privacy Report (Product → Archive → Validate App → Check privacy manifest) to catch undeclared Required Reason API usages before you submit.

## Detection

- **ID:** `no-privacy-manifest`
- **Severity:** `critical`
- **What to look for:** For iOS apps (ios-only or ios-and-android), search the entire `ios/` directory for `PrivacyInfo.xcprivacy`. If not found, this check fails immediately. If found, open the file and verify it contains all four required keys: `NSPrivacyAccessedAPITypes` (array of dictionaries with `NSPrivacyAccessedAPIType` and `NSPrivacyAccessedAPITypeReasons`), `NSPrivacyCollectedDataTypes` (array), `NSPrivacyTracking` (boolean), and `NSPrivacyTrackingDomains` (array, may be empty). Then cross-reference `NSPrivacyAccessedAPITypes` against code: search for `UserDefaults`/`NSUserDefaults` → must declare type `NSPrivacyAccessedAPICategoryUserDefaults`; `FileManager.default.urls(for:)` or `NSHomeDirectory()` → `NSPrivacyAccessedAPICategoryFileTimestamp`; `NSProcessInfo.processInfo` (systemUptime) → `NSPrivacyAccessedAPICategorySystemBootTime`; `NSFileSystemFreeSize`/`NSFileSystemSize` → `NSPrivacyAccessedAPICategoryDiskSpace`; `UIDevice.identifierForVendor` → `NSPrivacyAccessedAPICategoryUserDefaults` (IDFV is covered differently — check Apple docs); `CTTelephonyNetworkInfo` → `NSPrivacyAccessedAPICategoryUserDefaults`. In React Native and Expo apps, also search `node_modules/` for any pod that uses these APIs — their `PrivacyInfo.xcprivacy` files must be present (they're bundled with compliant SDK versions). Flag if a Required Reason API is used in source or via a dependency that lacks a compliant privacy manifest.
- **Pass criteria:** `PrivacyInfo. At least 1 implementation must be verified.xcprivacy` exists under `ios/`, contains all four required top-level keys, and all Required Reason APIs used in code or via dependencies are declared with at least one valid reason code. A partial or placeholder implementation does not count as pass. Report the count even on pass.
- **Fail criteria:** File is missing entirely; or present but missing required keys; or code/dependencies use Required Reason APIs that are not declared in the manifest.
- **Skip (N/A) when:** App targets Android only (no `ios/` directory detected, no iOS build configuration, no Expo iOS platform).
- **Detail on fail:** Cite the specific gap. Example: `"PrivacyInfo.xcprivacy missing from ios/ directory — required since May 2024 for all iOS app updates"` or `"NSPrivacyAccessedAPITypes declares UserDefaults but source uses NSProcessInfo.processInfo.systemUptime (SystemBootTime) — missing reason declaration"`
- **Remediation:** Apple has required privacy manifests for all app updates since May 1, 2024. Missing or incomplete manifests cause binary rejection before human review.
  1. Create `ios/[AppName]/PrivacyInfo.xcprivacy` as a property list with the four required keys
  2. For each Required Reason API your app uses, add the type and at least one reason code from Apple's list at https://developer.apple.com/documentation/bundleresources/privacy_manifest_files/describing_use_of_required_reason_api
  3. For Expo apps, add the `privacyManifests` key to your app config plugin or use the `expo-privacy-manifests` package
  4. Verify all third-party pods have their own `PrivacyInfo.xcprivacy` — run `find ios/ -name PrivacyInfo.xcprivacy` to enumerate them
  5. Use Xcode's Privacy Report (Product → Archive → Validate App → Check privacy manifest) to find gaps before submission

  Review the configuration in `src/` or `app/` directory for implementation patterns.

## External references

- external apple-privacy-manifest — https://developer.apple.com/documentation/bundleresources/privacy_manifest_files
- gdpr Art.5(1)(c)
- gdpr Art.13
- ccpa §1798.100

Taxons: regulatory-conformance, privacy-consent

HTML version: https://auditbuffet.com/patterns/ab-000464
