From fd90055ccd313abb264cf2beaebcf931e558d8eb Mon Sep 17 00:00:00 2001 From: NimBold Date: Wed, 10 Jun 2026 12:03:11 +0330 Subject: [PATCH] fix(security): prevent eager keychain password fetch on startup Defers fetching site login passwords until they are strictly needed (when a download starts or when viewing properties) to prevent the OS from showing the keychain prompt before the in-app primer UI. --- Sources/Firelink/DownloadController.swift | 9 +++++---- Sources/Firelink/DownloadPropertiesView.swift | 3 ++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Sources/Firelink/DownloadController.swift b/Sources/Firelink/DownloadController.swift index 2b1f3c6..ce020fa 100644 --- a/Sources/Firelink/DownloadController.swift +++ b/Sources/Firelink/DownloadController.swift @@ -503,6 +503,11 @@ final class DownloadController: ObservableObject { private func injectedEngineItem(from item: DownloadItem) -> DownloadItem { var engineItem = item + if engineItem.credentials != nil { + if let storedPassword = KeychainCredentialStore.password(for: engineItem.id) { + engineItem.credentials?.password = storedPassword + } + } let ua = settings.customUserAgent.trimmingCharacters(in: .whitespacesAndNewlines) if !ua.isEmpty, !(engineItem.requestHeaders?.contains(where: { $0.name.caseInsensitiveCompare("user-agent") == .orderedSame }) ?? false) { var headers = engineItem.requestHeaders ?? [] @@ -1044,10 +1049,6 @@ final class DownloadController: ObservableObject { adjusted.queueID = DownloadQueue.mainQueueID } - if adjusted.credentials != nil, let storedPassword = KeychainCredentialStore.password(for: adjusted.id) { - adjusted.credentials?.password = storedPassword - } - if adjusted.status == .completed && adjusted.progress != 1 { adjusted.progress = 1 shouldRewriteStoredDownloads = true diff --git a/Sources/Firelink/DownloadPropertiesView.swift b/Sources/Firelink/DownloadPropertiesView.swift index a95fd59..bfb7271 100644 --- a/Sources/Firelink/DownloadPropertiesView.swift +++ b/Sources/Firelink/DownloadPropertiesView.swift @@ -60,7 +60,8 @@ struct DownloadPropertiesView: View { if let credentials = item.credentials { _loginMode = State(initialValue: .custom) _username = State(initialValue: credentials.username) - _password = State(initialValue: credentials.password) + let storedPassword = KeychainCredentialStore.password(for: item.id) ?? credentials.password + _password = State(initialValue: storedPassword) } else { _loginMode = State(initialValue: .matching) _username = State(initialValue: "")