From 37d6cb54d2a4fc974637f573c3b96489c8dba45d Mon Sep 17 00:00:00 2001 From: Rocuts Date: Mon, 2 Mar 2026 12:31:08 -0500 Subject: [PATCH] iOS: harden Keychain storage with delete-then-add and accessibility attribute (cherry picked from commit cf122ce68ef4ebc7a63193c972c7f72dc7c54244) --- apps/ios/Sources/Gateway/KeychainStore.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/ios/Sources/Gateway/KeychainStore.swift b/apps/ios/Sources/Gateway/KeychainStore.swift index 1377d8517ef..4d1a000986e 100644 --- a/apps/ios/Sources/Gateway/KeychainStore.swift +++ b/apps/ios/Sources/Gateway/KeychainStore.swift @@ -18,6 +18,9 @@ enum KeychainStore { } static func saveString(_ value: String, service: String, account: String) -> Bool { + // Delete-then-add ensures kSecAttrAccessible is always applied. + // SecItemUpdate cannot change the accessibility level of an existing item, + // so a stale item created with a weaker policy would retain it on update. let data = Data(value.utf8) let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, @@ -25,10 +28,7 @@ enum KeychainStore { kSecAttrAccount as String: account, ] - let update: [String: Any] = [kSecValueData as String: data] - let status = SecItemUpdate(query as CFDictionary, update as CFDictionary) - if status == errSecSuccess { return true } - if status != errSecItemNotFound { return false } + SecItemDelete(query as CFDictionary) var insert = query insert[kSecValueData as String] = data