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
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
10 changes: 7 additions & 3 deletions Sources/Browseroute/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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]) {
Expand Down
10 changes: 8 additions & 2 deletions Sources/Browseroute/Updater.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 "
Expand All @@ -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() {
Expand Down
Loading