DEV Community

孫昊
孫昊

Posted on

Verify Your Own iOS App Privacy Claims with nm (Real Test, Real Result)

TL;DR: Privacy Manifest declarations are just XML. The binary is the proof. Here's how to use nm and otool to verify your own iOS app actually does what its Privacy Manifest claims — and why every privacy-first indie should ship with this verification command in their README.


The privacy gap

Apple's Privacy Manifest (introduced 2024, mandatory 2025+) is a YAML/plist file declaring what data your app collects. Apple's review reads this and shows users a labeled "Data this app collects" page in the App Store.

But the manifest is just a declaration. Nothing physically prevents your app from collecting data not declared.

Real privacy-first apps need a verification step. Here's the one I use.

The setup

I have 4 indie iOS apps with one shared claim: zero data collection, zero networking, zero analytics SDKs. The Privacy Manifest declares it. The binary backs it up.

The verification: nm (the symbol-table reader, comes with Xcode) shows every external symbol your binary references. If the binary uses URLSession, NSURLConnection, Network.framework, or any analytics SDK — the symbols appear in nm output.

If they're absent, the binary literally cannot phone home.

The command

nm -gU AutoChoice.app/AutoChoice | grep -iE 'URL|HTTP|Network|Analytics'
Enter fullscreen mode Exit fullscreen mode

Breakdown:

  • nm — list symbols
  • -g — only externally visible symbols (the ones the OS would link to)
  • -U — only undefined symbols (the ones the binary needs but doesn't provide itself; these are calls into iOS frameworks)
  • AutoChoice.app/AutoChoice — the binary inside the .app bundle (extract from .ipa or pull from device)

Run it on my AutoChoice binary:

$ nm -gU AutoChoice.app/AutoChoice | grep -iE 'URL|HTTP|Network|Analytics'
(no output)
Enter fullscreen mode Exit fullscreen mode

Zero output = zero networking symbols in the binary. The app cannot make a network request even if it wanted to.

Compare to a typical app

Most iOS apps have hundreds of networking symbols:

$ nm -gU SomeOtherApp.app/SomeOtherApp | grep -iE 'URL|HTTP|Network' | head
                 U _CFURLCopyAbsoluteURL
                 U _CFURLCreateAbsoluteURLWithBytes
                 U _CFURLCreateWithString
                 U _NSURLConnectionDidFailLoadingError
                 U _NSURLProtectionSpaceHTTPS
                 U _NSURLSessionConfigurationDefault
                 ... (300+ more)
Enter fullscreen mode Exit fullscreen mode

300+ networking symbols means: URLSession.shared.dataTask(with: ...) is somewhere in the binary. Could be analytics, could be feature loading, could be ads. The point is: it CAN make requests.

A truly offline app shouldn't have these.

Other categories worth checking

# Analytics SDKs (look for known framework names)
nm -gU AutoChoice.app/AutoChoice | grep -iE 'Firebase|Mixpanel|Amplitude|Adjust|AppsFlyer|Segment'

# Tracking IDs
nm -gU AutoChoice.app/AutoChoice | grep -iE 'Advertising|IDFA|IDFV|TrackingTransparency'

# Background tasks
nm -gU AutoChoice.app/AutoChoice | grep -iE 'BackgroundTask|BGTask'
Enter fullscreen mode Exit fullscreen mode

For my apps: all empty.

How to publish this verification on YOUR site

Add to your app's README + privacy page:

## Verify the privacy claim yourself

Privacy Manifest is a declaration. The binary is the proof. After downloading
from the App Store:

1. Get the binary from Settings → General → iPhone Storage → [App] → Show Data
2. Or extract from .ipa (rename .ipa to .zip, unzip, find Payload/<App>.app/<App>)
3. Run:
   nm -gU AutoChoice.app/AutoChoice | grep -iE 'URL|HTTP|Network'

Empty output = no networking symbols in the binary = the app cannot phone home.
Enter fullscreen mode Exit fullscreen mode

Then take a screenshot of the empty output and host it on your privacy page. That's a verifiable claim, not a marketing claim.

Why most apps don't do this

Three reasons:

  1. They have networking they don't disclose. Most apps use SDKs that phone home for analytics, crash reporting, or feature flags. Removing all of them means losing those tools.
  2. They don't think users will check. Most users won't run nm. But the few who do (security researchers, privacy bloggers) will tell their networks.
  3. It's harder than it looks. SwiftUI apps often pull in Combine which transitively includes URLSession. Building a truly offline app requires deliberate architecture choices.

For my apps, the deliberate choices were:

  • No analytics SDK
  • No crash reporting (use Apple's built-in only, which doesn't go through your binary)
  • No remote config (use bundled defaults)
  • No image CDN (bundle all images at compile time)
  • No font CDN (use system fonts only)

This costs maybe 5% feature flexibility for 95% privacy verifiability. Worth it for indie apps where privacy is the differentiator.

Edge cases

Static frameworks: If you statically link a framework that uses networking, nm will show its symbols too. So check your build configuration — dynamic linking isolates the framework, static linking embeds it in your binary.

Swift symbol mangling: Swift symbols are mangled. Use swift demangle to read them:

nm -gU MyApp.app/MyApp | swift demangle | grep -i 'network'
Enter fullscreen mode Exit fullscreen mode

Apple framework symbols: Some Apple frameworks (Combine, SwiftUI) reference URL types internally. These are fine — they're part of the OS, not your code making requests. nm -U shows all undefined symbols including these. Filter for non-prefixed ones (_$s is Swift, _NS is Foundation):

nm -gU MyApp.app/MyApp | grep -E '^\s+U _[a-z]' | head
Enter fullscreen mode Exit fullscreen mode

This shows only your symbols, not Apple's.

The bigger point

Privacy is a verifiable property, not a marketing claim. Apps that say "we respect your privacy" without showing the binary verification are doing PR. Apps that publish the nm command and the empty output are doing actual privacy.

In 2026 with regulators (GDPR, EU DMA, US state privacy laws) tightening, the verifiable claim is increasingly the legal claim. PR claims will fail audits.

Source

All 4 of my iOS apps' Privacy Manifests + verification scripts: github.com/jiejuefuyou

  • AutoChoice / AltitudeNow / DaysUntil / PromptVault — all MIT licensed, all empty nm output

If you're building a privacy-first iOS app and want the full 60-day verifiable-privacy playbook: iOS Indie Launch Playbook ($19) — includes the Privacy Manifest configuration that passes Apple Review on first try.

Top comments (0)