Summary
A third-party PKG installer that ships a custom Installer Plugin no longer displays one of its selection panes. The plugin bundle appears not to be loaded, so the pane that it provides is silently skipped and the user cannot choose the intended installation option.
This behavior started with recent macOS releases and did not occur on the immediately preceding versions, so it looks like a regression.
Environment
Machine: MacBook Pro 14-inch (M3)
Affected builds:
- macOS 27.0 (26A428)
- macOS 26.7 (25G229)
- macOS 15.8 (24H23)
Not affected:
- macOS 26.6 and earlier
- macOS 15.7 and earlier
Reproducibility: every time
Plugin binary: Mach-O 64-bit bundle, x86_64 only (no arm64 slice)
Steps to Reproduce
- Download the Epson iProjection Ver.4.04 installer from the vendor support site: https://support.epson.net/setupnavi/?LG2=EN&OSC=MI&PINF=vpapp&MKN=EB-770Fi
- Mount the downloaded disk image and run the PKG installer.
- Step through the installer GUI and observe the pane transitions.
Expected Result
The installer GUI shows the "Application type" selection pane provided by the bundled Installer Plugin.
Actual Result
The "Application type" pane is never shown. The installer proceeds as if the plugin did not exist, and the user cannot select the installation type.
What I Checked
1. The plugin is present inside the PKG
pkgutil --expand-full PKG_PATH DEST_DIR
The expanded payload contains the plugin bundle and its Mach-O executable under Contents/MacOS.
2. Architecture of the plugin binary
file DEST_DIR/PluginName.bundle/Contents/MacOS/PluginName
Result: Mach-O 64-bit bundle x86_64. It is a single-architecture binary with no arm64 slice.
3. The plugin is actually touched at install time
sudo fs_usage -w -f filesys
InstallerRemotePluginService-x86 opens the plugin executable inside the installer's temporary directory (a path under /private/tmp/com.apple.installer* ). So the plugin is reached as a load target, but the pane still does not appear.
4. Code signature validation
When the installer is launched directly from the mounted disk image, code signature validation fails with:
Too many levels of symbolic links
My working theory is that the bundle contents are turned into symbolic links when the plugin is expanded, and that this causes codesign validation to fail, so the plugin is rejected before it can register its pane.
5. Code evaluation by syspolicyd
log stream --info --debug --predicate 'process == "syspolicyd"'
GK package assessment, GK process assessment and GK performScan entries are present, so Gatekeeper evaluation itself is running. The following also appears:
Error Domain=NSOSStatusErrorDomain Code=-67062
Unsigned code in: PST: (path: REDACTED), (team: (null)), (id: (null)), (bundle_id: (null))
The PST path is anonymized in the log, so I could not confirm that this particular assessment refers to the plugin bundle.
6. XProtect evaluation results differ between versions
log stream --info --debug --predicate 'process == "syspolicyd"'
On the versions where the installer works correctly, the GK Xprotect results lines explicitly include a file URL pointing at the plugin bundle inside the installer temporary directory.
On the affected builds, searching the same log for the plugin bundle name returns zero matches. That suggests the bundle is not being processed as an XProtect evaluation target at all on the newer builds.
Question
Was there a change in how Installer Plugins are expanded or validated in these releases, in particular around symlinked bundle contents or single-architecture x86_64 plugins?
Any guidance on the supported way to ship an Installer Plugin so that it is still loaded on current macOS would be appreciated.
Too many levels of symbolic links
That’s a known issue.
I’m not sure if your Intel-only plug-in is relevant here — as far as I know the other folks who’ve hit this have plug-ins with Intel and Apple silicon code — but, regardless, that’s something you need to fix. We’re rapidly approaching the end of Rosetta 2.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"