Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions macos/ForgePlatformInstaller/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,10 @@ startup. It asks for explicit confirmation without `--yes`, rechecks installer
currency immediately before `SMAppService` registration, and reports native
`ENABLED` or `REQUIRES_APPROVAL` separately. Registration never implies that
the product-operation backend or reboot persistence is ready.
The CLI is a second executable inside the signed app. Current-bundle
architecture admission reads the sealed `CFBundleExecutable` and checks the
fixed GUI executable rather than using Foundation's process-relative
`executableURL`, which can point at the running CLI.
An `ENABLED` system job is accepted only after a fixed-label native readback
confirms the registered parent bundle, Team, helper program and exact current
installer version. An older registered helper fails closed; registration does
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,16 @@ enum MacOSInstallerExecutableArchitecture {
static func requireThinARM64Executable(in bundleURL: URL) throws {
guard bundleURL.isFileURL,
let bundle = Bundle(url: bundleURL),
let executableURL = bundle.executableURL,
executableURL.deletingLastPathComponent().lastPathComponent == "MacOS",
executableURL.lastPathComponent == "ForgePlatformInstaller" else {
bundle.infoDictionary?["CFBundleExecutable"] as? String ==
"ForgePlatformInstaller" else {
throw MacOSInstallerExecutableArchitectureError.invalidBundleExecutable
}
// Foundation's `executableURL` points at the *running* CLI when it is
// the second executable in this app. The sealed Info.plist instead
// identifies the one fixed GUI executable covered by this contract.
let executableURL = bundleURL.appendingPathComponent(
"Contents/MacOS/ForgePlatformInstaller", isDirectory: false
)
try requireThinARM64Executable(at: executableURL)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,26 @@ final class MacOSInstallerExecutableArchitectureTests: XCTestCase {
try MacOSInstallerExecutableArchitecture.requireThinARM64Executable(in: bundle)
)

let validBundle = root.appendingPathComponent("ValidInstaller.app", isDirectory: true)
try FileManager.default.copyItem(at: bundle, to: validBundle)
try thinARM64Header().write(to: validBundle.appendingPathComponent(
"Contents/MacOS/ForgePlatformInstaller"
))
XCTAssertNoThrow(
try MacOSInstallerExecutableArchitecture.requireThinARM64Executable(in: validBundle)
)

let wrongInfoBundle = root.appendingPathComponent("WrongInfo.app", isDirectory: true)
try FileManager.default.copyItem(at: validBundle, to: wrongInfoBundle)
var wrongInfo = info
wrongInfo["CFBundleExecutable"] = "forge-platform-installer"
try PropertyListSerialization.data(
fromPropertyList: wrongInfo, format: .xml, options: 0
).write(to: wrongInfoBundle.appendingPathComponent("Contents/Info.plist"))
XCTAssertThrowsError(
try MacOSInstallerExecutableArchitecture.requireThinARM64Executable(in: wrongInfoBundle)
)

// Use a separate inode for the positive path so this assertion does
// not depend on Foundation's Bundle or file-resource caches after the
// rejected bundle inspection above.
Expand Down
Loading