diff --git a/CHANGELOG.md b/CHANGELOG.md index 767ec04..467a867 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Applied rate-limiting and text length bounds to the custom `firelink://` scheme to mitigate DoS and injection attempts. ### Fixes +- Restored the UUID fallback for token generation to prevent silent failures if secure random byte generation fails. +- Hardened local API security by immediately rejecting requests if the expected pairing token is completely empty. - Implemented a thread-safe cleanup mechanism for temporary directories to resolve a concurrency race condition during engine cancellation. ## [0.7.0] - 2026-06-11 diff --git a/Extensions/Firefox b/Extensions/Firefox index fc078ef..3301425 160000 --- a/Extensions/Firefox +++ b/Extensions/Firefox @@ -1 +1 @@ -Subproject commit fc078ef6ad672d7f3e83008f0033db7480cc3ff0 +Subproject commit 330142590bb464708ec074a44929fa03b1fc7b89 diff --git a/Sources/Firelink/LocalExtensionServer.swift b/Sources/Firelink/LocalExtensionServer.swift index a9cdd84..9cad850 100644 --- a/Sources/Firelink/LocalExtensionServer.swift +++ b/Sources/Firelink/LocalExtensionServer.swift @@ -156,6 +156,10 @@ final class LocalExtensionServer: @unchecked Sendable { } let expectedToken = currentPairingToken + guard !expectedToken.isEmpty else { + return .forbidden + } + let bodyString = String(data: request.body, encoding: .utf8) ?? "" guard let signatureHex = request.header(named: "x-firelink-signature"), let timestampStr = request.header(named: "x-firelink-timestamp"), diff --git a/Sources/Firelink/Settings/IntegrationSettingsPane.swift b/Sources/Firelink/Settings/IntegrationSettingsPane.swift index f1d70e8..748fbe1 100644 --- a/Sources/Firelink/Settings/IntegrationSettingsPane.swift +++ b/Sources/Firelink/Settings/IntegrationSettingsPane.swift @@ -61,6 +61,8 @@ struct IntegrationSettingsPane: View { let status = SecRandomCopyBytes(kSecRandomDefault, bytes.count, &bytes) if status == errSecSuccess { settings.extensionPairingToken = Data(bytes).base64EncodedString() + } else { + settings.extensionPairingToken = UUID().uuidString } } )