diff --git a/CHANGELOG.md b/CHANGELOG.md index b175425..0eb4f39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,4 +13,4 @@ All notable changes to Browseroute are documented here (Keep a Changelog style). - App icon: charcoal squircle with a routing Y (About, Finder, README). - Developer ID-signed, notarized GitHub releases (same methodology as yap and TickerBar) and a Homebrew cask. -- Sparkle EdDSA key baked in; Check for Updates is live on Developer ID-signed GitHub builds (ad-hoc and Homebrew stay off). +- Sparkle EdDSA key baked in; Check for Updates is live on Developer ID-signed GitHub builds (ad-hoc and Homebrew stay off). The cert check runs after launch and does not hash sealed resources. diff --git a/Sources/Browseroute/AppDelegate.swift b/Sources/Browseroute/AppDelegate.swift index d6cd211..3d43e2b 100644 --- a/Sources/Browseroute/AppDelegate.swift +++ b/Sources/Browseroute/AppDelegate.swift @@ -5,14 +5,18 @@ import os @MainActor final class AppDelegate: NSObject, NSApplicationDelegate { private var statusController: StatusItemController? - private let updater: any UpdaterProviding = makeUpdater() func applicationDidFinishLaunching(_: Notification) { NSApp.setActivationPolicy(.accessory) - AppServices.updater = updater AppNotify.requestAuthorization() statusController = StatusItemController() - updater.start() + // Sparkle (and the Developer ID check) after this turn so a cold-start + // URL open is already routed. + Task { @MainActor in + let updater = makeUpdater() + AppServices.updater = updater + updater.start() + } } func application(_: NSApplication, open urls: [URL]) { diff --git a/Sources/Browseroute/Updater.swift b/Sources/Browseroute/Updater.swift index 9c4a3c2..ff63c4f 100644 --- a/Sources/Browseroute/Updater.swift +++ b/Sources/Browseroute/Updater.swift @@ -58,7 +58,9 @@ func makeUpdater() -> any UpdaterProviding { } /// Team 92X3ACDPD2 Developer ID Application. Ad-hoc, Apple Development, - /// and other-team signatures do not match. + /// and other-team signatures do not match. Skip sealed-resource hashing: + /// the requirement still evaluates the cert chain, and a cold-start URL + /// open should not wait on Sparkle.framework's CodeResources. static let developerIDRequirement = "anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and " + "certificate leaf[field.1.2.840.113635.100.6.1.13] exists and " @@ -76,7 +78,11 @@ func makeUpdater() -> any UpdaterProviding { &requirement, ) guard parsed == errSecSuccess, let requirement else { return false } - return SecStaticCodeCheckValidity(staticCode, [], requirement) == errSecSuccess + return SecStaticCodeCheckValidity( + staticCode, + SecCSFlags(rawValue: kSecCSDoNotValidateResources), + requirement, + ) == errSecSuccess } override init() {