Repository navigation
Apply per-bundle entitlements - #3
Open
TartanLeGrand wants to merge 3 commits into
Open
TartanLeGrand wants to merge 3 commits into
TartanLeGrand wants to merge 3 commits into
Conversation
This was referenced Oct 12, 2026
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars.
|
This was referenced Oct 12, 2026
A leaf that is its own issuer has no chain to embed, so build the CMS signature without one instead of failing. Useful for tests.
Zupersign built a single asset from entitlements[0] and applied it to every executable in the app. Build one asset per entitlements_data_t instead, bound to the bundle at its bundle_path, and let SignNode pick the asset of each bundle (falling back to the app's).
Making room for the signature replaces the executable with a new file, which dropped the executable bit.
TartanLeGrand
force-pushed
the
feat/per-bundle-entitlements
branch
from
October 26, 2026 23:27
b20784b to
6ad8727
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Lets Zupersign sign each bundle of an app with its own entitlements, so app extensions stop inheriting the entitlements of the main app. This is the zsign half of xtool-org/xtool#131.
Today
zsign_signbuilds a singleZSignAssetfromentitlements[0]and applies it to every executable. xtool works around it by passing only the root app's entitlements (the "temp hack" inSigner.sign), so an extension is signed with the app's entitlements. For development signing that is mostly harmless; for distribution it is not, because each bundle must match its own provisioning profile (for example a widget must not claimaps-environmentwhen its profile does not grant it).Three commits:
ZSignAssetperentitlements_data_t, bound to its bundle bybundle_pathrelative to the app directory (/for the app itself).ZBundle::SignNodepicks the asset of the bundle it is signing and falls back to the app's asset for bundles without an entry. The app's asset is moved to the front of the list becauseSignFolderuses the front as the default. When a provisioning profile matches a nested bundle by application identifier, only assets that actually carry profile data are considered, and the bundle keeps its bound asset otherwise. With a single entitlements entry (what xtool passes today) the behaviour is unchanged.ZMachO::ReallocCodeSignSpacewrites a new file and renames it over the original, which dropped the executable bit (the main binary came out0644while an extension kept0755). The mode of the original file is now restored after the rename, for thin and fat binaries.How was it tested?
zsign has no test suite of its own, so it is exercised through xtool (Linux x86_64, Podman, Swift 6.4), with xtool depending on a branch that combines this PR with #4 (SHA-256 only CodeDirectory) and #5 (free space check):
swift buildof theZupersigntarget on this branch alone.embedded.mobileprovisionper bundle and the executable bits. The permission test fails without commit 2.xtool signcommand proposed in signing: sign for distribution with an existing identity xtool#326. The signed entitlements of the app and of the extension are identical, key for key and value for value, to those of the Xcode export of the same app; the extension no longer carries the app'saps-environment. App Store Connect accepted the uploads: the builds reachedVALIDin about 2 minutes and installed through TestFlight on an iPhone with iOS 27.Not tested: the standalone zsign builds (
linux/,macos/,windows/), only the SwiftPM target.Remaining differences from codesign output that this PR does not change: the extension uses 4K pages (codesign 16K), dylibs get an empty entitlements blob, and
files2entries keep the legacy SHA-1hashkey. None of them blocked App Store processing.Merge note: #4 edits the same
asset.Init(...)call inZupersign.cpp; whichever lands second needs a one-line rebase. A release containing this PR is needed before xtool can drop its workaround.Developed with AI assistance; validated on device and against App Store Connect as described above.