Skip to content

EAS Build drops iOS entitlements (associated-domains, application-groups) #4162

Description

@olcaneristi

Build/Submit details page URL

Failing: https://expo.dev/accounts/hayatpay/projects/hayatpay-app/builds/57d2c9f9-935a-41c2-88b9-bde8a32980fa
Passing (same commit): https://expo.dev/accounts/hayatpay/projects/hayatpay-app/builds/b0db91ab-d561-4a14-a58c-8a0cb52092e4
Passing (extension disabled): https://expo.dev/accounts/hayatpay/projects/hayatpay-app/builds/5ae7953e-3d70-4170-a3cc-a0688872dd8a

Summary

Our iOS builds silently lose all entitlements on the main app target in the signed IPA —com.apple.developer.associated-domains, aps-environment and com.apple.security.application-groups are all missing, which breaks Universal Links. The app extension in the same IPA is signed correctly. This setup worked for ~10 months and broke with no change on our side: app.config.ts, eas.json, package.json and every config plugin are byte-identical between our last good build (prod 1.36.0, 2026-07-14) and the first bad one (prod 1.39.0, 2026-07-25) — only JS/TS application code changed in that window. Same @expo/config-plugins (10.1.2), same pinned image (macos-sequoia-15.6-xcode-26.2).

The entitlements are correct everywhere we can inspect before signing: expo config --type introspect, the build log's own "Using app configuration" output, the .entitlements file written by expo prebuild, CODE_SIGN_ENTITLEMENTS in project.pbxproj, and the provisioning profile (which grants associated-domains => "*"). Disabling the extension plugin — with no other change — makes the main app's entitlements reappear. It is also not deterministic: of 4 builds from the identical commit, 1 was correct and 3 were not.

Managed or bare?

Managed — ios/ and android/ are gitignored (0 native files in the repo), so EAS runs expo prebuild on every build. Note: expo-env-info reports "bare" only because a local ios/ directory exists on my machine from running prebuild manually.

Environment

expo-env-info 2.1.0 environment info:
System:
OS: macOS 26.4.1
Shell: 5.9 - /bin/zsh
Binaries:
Node: 24.3.0
Yarn: 1.22.22
npm: 11.4.2
Watchman: 2025.06.30.00
Managers:
CocoaPods: 1.16.2
SDKs:
iOS SDK:
Platforms: DriverKit 25.2, iOS 26.2, macOS 26.2, tvOS 26.2, visionOS 26.2, watchOS 26.2
IDEs:
Android Studio: 2025.3
Xcode: 26.2/17C52
npmGlobalPackages:
eas-cli: 18.6.0
Expo Workflow: bare

expo-doctor: 17/17 checks passed. No issues detected!

Expo SDK: 53.0.0 (expo 53.0.27, react-native 0.79.6)
@expo/config-plugins: 10.1.2
eas.json ios image: macos-sequoia-15.6-xcode-26.2

Error output

No error is emitted — the build succeeds. The failure is silent: entitlements are missing from the signed binary, so Universal Links stop working with no diagnostic. (Identifiers below are redacted; happy to share them privately.)

Signed main app in the failing build — only the keys EAS/Xcode adds itself:

$ codesign -d --entitlements - Payload/MyApp.app
[Dict]
    [Key] application-identifier
    [Key] beta-reports-active
    [Key] com.apple.developer.team-identifier
    [Key] get-task-allow

Signed extension in the very same IPA — its entitlement is applied correctly:

$ codesign -d --entitlements - Payload/MyApp.app/PlugIns/MyExtension.appex
[Dict]
    [Key] application-identifier
    [Key] beta-reports-active
    [Key] com.apple.developer.team-identifier
    [Key] com.apple.security.application-groups   <-- present here
    [Key] get-task-allow

Main app .entitlements written by expo prebuild before the build (correct):

<key>aps-environment</key><string>production</string>
<key>com.apple.developer.associated-domains</key>
<array>
  <string>applinks:REDACTED-1.go.link</string>
  <string>applinks:REDACTED-2.go.link</string>
  <string>applinks:REDACTED-3.adj.st</string>
</array>
<key>com.apple.security.application-groups</key>
<array><string>group.com.example.app</string></array>

For reference, the same build with the extension plugin disabled produces a main app signed with associated-domains, aps-environment and application-groups all present.

Reproducible demo or steps to reproduce from a blank project

I don't have a blank-project repro, and I want to be upfront that the extension target is created by a project-local config plugin — so this could still be our bug. But the strongest argument against that is that we changed nothing: that plugin was last modified 2025-10-06, and app.config.ts, eas.json, package.json and every plugin file are byte-identical (verified with git diff) between our last good build (2026-07-14) and the first bad one (2026-07-25). Only JS/TS application code changed in that window. The same plugin had been producing correctly signed builds for ~10 months.

  • env vars — the build log's own "Using app configuration" shows the correct values
  • provisioning profile — grants associated-domains: "*" and both app groups; the log shows the expected profile UUID being used
  • regenerating credentials from scratch
  • expo / @expo/config-plugins versions — 10.1.2 in both passing and failing builds
  • the iOS build image — pinned to macos-sequoia-15.6-xcode-26.2 throughout
  • duplicate or mistyped targets in project.pbxproj — verified 2 targets with correct product types, and CODE_SIGN_ENTITLEMENTS pointing at the right file for each
  • local expo prebuild --clean output — always correct, and ios/ is gitignored so EAS prebuilds from scratch on every build

Happy to run any diagnostic command against a build, or share the redacted identifiers privately.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs reviewIssue is ready to be reviewed by a maintainer

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions