Provisioning

Inspect a Provisioning Profile Inside an IPA

Decode the profile embedded in the delivered IPA and verify its identity, expiration, entitlements, certificate records, and device membership.

The provisioning profile that matters is the one embedded in the delivered IPA. A profile in the Apple portal, Downloads folder, Xcode cache, or CI signing store does not prove what the tester received.

This workflow answers a focused evidence question: Does this exact IPA contain a profile that names the intended app, team, validity period, signing authorization, entitlements, and—when the distribution method is device-bound—the target UDID?

A matching ProvisionedDevices entry is useful evidence, but it does not prove the entire IPA is valid.

Preserve the artifact before inspection

Work on a copy and record provenance before extraction:

shasum -a 256 ClientBuild.ipa
mkdir ClientBuild-unpacked
unzip -q ClientBuild.ipa -d ClientBuild-unpacked

APP_PATH=$(find ClientBuild-unpacked/Payload \
  -maxdepth 1 -name '*.app' -print -quit)

plutil -extract CFBundleIdentifier raw -o - \
  "$APP_PATH/Info.plist"

Record who supplied the IPA, its filename, version/build, intended distribution method, and checksum. If the file behind the tester link later produces a different checksum, profile analysis of your local copy does not describe the delivered artifact.

Do not edit and re-zip the extracted app. Any modification to signed bundle content invalidates the existing signature.

Decode the embedded profile

For an iOS app that carries embedded.mobileprovision:

security cms -D \
  -i "$APP_PATH/embedded.mobileprovision" \
  -o /tmp/client-profile.plist

plutil -lint /tmp/client-profile.plist

Apple describes a provisioning profile as a property list wrapped in a Cryptographic Message Syntax signature. Apple also warns that the profile’s internal property-list format is not a stable product API and can change. Use these fields for diagnosis and human-reviewed release evidence, not as an undocumented permanent provisioning engine.

Modern profiles can also contain a DER-encoded representation used by the operating system. A readable plist is powerful diagnostic evidence; it is not permission to rewrite or forge profile contents.

Read the fields that identify the profile

Start with fields that distinguish one profile revision from another:

plutil -extract Name raw -o - /tmp/client-profile.plist
plutil -extract UUID raw -o - /tmp/client-profile.plist
plutil -extract CreationDate raw -o - /tmp/client-profile.plist
plutil -extract ExpirationDate raw -o - /tmp/client-profile.plist
plutil -extract TeamIdentifier xml1 -o - /tmp/client-profile.plist

Interpret them carefully:

If a key is absent, stop and identify the profile type before assuming corruption. Different distribution methods do not expose identical fields.

Check the application identifier and entitlement allowlist

Read the profile’s authorization:

plutil -extract Entitlements.application-identifier raw \
  -o - /tmp/client-profile.plist

plutil -extract Entitlements xml1 \
  -o /tmp/profile-entitlements.plist \
  /tmp/client-profile.plist

Then inspect what the app actually claims:

codesign --display --entitlements :- "$APP_PATH" \
  > /tmp/app-entitlements.plist 2>/dev/null

plutil -extract application-identifier raw \
  -o - /tmp/app-entitlements.plist

The profile’s application-identifier represents the authorized App ID context. Compare its bundle-ID portion with the app’s CFBundleIdentifier and signed application identifier. The profile entitlements are an authorization allowlist; the app’s signed entitlements are its actual claims. The app cannot safely claim a restricted capability the profile does not authorize.

Use Bundle ID and Provisioning Profile Mismatch when identifiers or entitlements disagree. This page establishes the evidence; the mismatch page owns that repair branch.

Check the target device where applicable

For a Development or Ad Hoc profile that authorizes specific registered devices:

plutil -extract ProvisionedDevices xml1 \
  -o /tmp/provisioned-devices.plist \
  /tmp/client-profile.plist

plutil -p /tmp/provisioned-devices.plist

Compare the target physical device’s validated UDID character for character. The browser-local UDID Validator can normalize presentation separators and catch obvious input errors without uploading the value, but it cannot prove that the identifier belongs to the intended phone or Apple team.

If the target is absent, use Device Not in Provisioning Profile to find where it fell out of the authorization chain. Add a Device to an Existing Provisioning Profile owns the update and replacement-artifact workflow.

Do not expect every profile to have a device list

Profiles for different distribution methods do not have identical diagnostic fields. A device-bound Development or Ad Hoc profile can expose ProvisionedDevices. App Store and TestFlight workflows should not be diagnosed as though every build authorizes an enumerated tester UDID.

First identify the distribution method. An absent ProvisionedDevices key can be expected for a non-device-bound route; it does not by itself prove that the profile is broken.

Inspect certificate authorization

The profile’s DeveloperCertificates property contains certificate records authorized to sign code covered by the profile. It does not contain the private key.

Confirm the field exists and understand its scope:

plutil -extract DeveloperCertificates xml1 \
  -o /tmp/profile-certificates.plist \
  /tmp/client-profile.plist

plutil -p /tmp/profile-certificates.plist

For an exact identity comparison, inspect the signing authority reported by codesign and compare the certificate fingerprint, serial, validity, and team context with the certificate data authorized by the profile. Check an IPA’s Code Signature is the canonical signing-evidence page. If the identity is not authorized by this profile, use Profile and Signing Certificate Mismatch.

Do not paste full base64 certificate blocks or decoded profiles into public tickets. Public certificate material is not a signing secret, but profiles can contain device identifiers, team details, entitlements, and operational data that do not belong in an open issue.

Inspect nested extensions and apps

The main .app is not necessarily the only provisioned target. Enumerate nested code:

find "$APP_PATH" -type d \
  \( -name '*.appex' -o -name '*.app' \) -print

An extension or nested app can have its own bundle identifier, entitlements, signature, and embedded profile. Repeat the relevant profile checks for each target that has embedded.mobileprovision.

Do not assume the main app’s device membership, App ID, or certificate authorization proves every extension is compatible. A wrong nested profile can still break installation or launch even when the outer profile looks correct.

What device membership proves—and does not prove

Finding the target UDID in ProvisionedDevices proves only that the decoded profile claims that device in a device-bound authorization set.

It does not prove:

Route each proven mismatch to its owner page: Expired Provisioning Profile, Certificate/Profile Mismatch, Bundle ID/Profile Mismatch, or IPA Signature Inspection.

Compare an old IPA with its replacement

Do not compare portal screenshots. Extract both immutable artifacts into separate directories and record the same evidence for each:

  1. SHA-256 checksum, filename, version, and build.
  2. Main app bundle identifier and signed application identifier.
  3. Profile Name, UUID, CreationDate, and ExpirationDate.
  4. Team context and certificate authorization.
  5. Target device membership where the profile is device-bound.
  6. Signed entitlements and code-signature verification outcome.
  7. Profile and signing context for each nested extension or app.

A replacement intended to add one tester should show a changed profile revision and the reviewed device-set change. It should not unexpectedly change the team, bundle identity, entitlements, certificate, or other device membership.

The most useful acceptance record is concise: old checksum/profile UUID, new checksum/profile UUID, target UDID present or absent, expiration, application identifier, signing verification result, and the exact delivered checksum.

Handle the evidence safely

Keep decoded profiles and UDID lists in an access-controlled diagnostic location and delete temporary files according to the team’s retention policy. In support tickets, share only the minimum redacted evidence needed to explain the mismatch.

Never post a full profile, full device list, Apple Account credentials, private keys, P8 files, P12 files, or the IPA itself to a public issue. The purpose of inspection is to reduce uncertainty without expanding access to sensitive release material.

Related next steps

Next step. Preserve the artifact evidence, then correct only the first proven mismatch. Join Early Access.

Sources