expo / expo/eas-cli

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

Open
#4,162 2 comments 1 reaction 0 assignees View on GitHub
needs review
Dominant language
TypeScript
Stars
1.4k
Forks
236
Avg merge
3d 1h
Merged PRs (30d)
91

Description

### 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):

aps-environmentproduction
com.apple.developer.associated-domains

applinks:REDACTED-1.go.link
applinks:REDACTED-2.go.link
applinks:REDACTED-3.adj.st

com.apple.security.application-groups
group.com.example.app

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.

Contributor guide

Open the contributing guide

Research direction

Start by comparing the passing and failing EAS build logs, expo prebuild output, and signed IPA entitlements. Inspect the project-local extension config plugin alongside app.config.ts, eas.json, package.json, and the generated project settings. Done means identifying why the main app target loses entitlements and verifying with codesign that a fix preserves them while the extension remains correct.

Written by the indexing model from the issue text.

Assessment

Tech stack
react-native, typescript
Domain
build-system, cli, devops, mobile
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.