Repository navigation
iOS: Add service and accessGroup options - #24
Conversation
|
Hi Takuya, I didn't get the time today to review it myself, but an AI review found the following: I found 7 issues in this PR. The first three are correctness bugs in the iOS keychain scoping, and all three can silently delete or expose items. The rest are inconsistencies and cleanup. Correctness
Inconsistencies
Cleanup
I'd block on 1–3 before merging, since each one can delete keychain data silently. 4 and 5 are worth fixing in this PR too. I will take a more in-depth look tomorrow, but you can review these and see if they are valid or not? |
PR OP-Engineering#24 review flagged three cases where a query could match items beyond the intended one: a nil bundle identifier or unconvertible service left kSecAttrService out, an unconvertible accessGroup silently dropped the group filter, and an omitted accessGroup matched copies in every group. Fail when a scope attribute can't be resolved, and pin an omitted accessGroup to the app's default group, found once with a probe item. Note: inkdrop://note/s2IGKjCd
PR OP-Engineering#24 review flagged that get and del threw where set returned an error. Invalid params (a non-string service or accessGroup) now throw from get and del, the same way a missing key does, and set returns { error }. Runtime failures, such as a scope that can't be resolved, return { error } from all three, and del now returns an object on both platforms. Android type-checks service and accessGroup too, so a value rejected on iOS is no longer silently accepted there. Note: inkdrop://note/s2IGKjCd
ItemScope is exported so callers can type the shared scope object they pass to set, get and del. readOptionalString no longer calls hasProperty first, since getProperty already yields undefined for a missing property. Note: inkdrop://note/s2IGKjCd
|
Sorry to bug you on your trip and thanks for checking! 1–3: No more unscoped keychain queries (1254aa6)
Open question on 3: compatibility for existing apps Pinning to the default group has two side effects for apps that don't pass
Options I see:
I lean towards (b) plus the fix for 2, but I'd like your take before changing it. 4–5: Error handling (d6f57a8)
6–7: Cleanup (aa43a12)
The example app's test suite passes on the iOS 26.5 simulator and the Android API 36 emulator. |
There was a problem hiding this comment.
Hi, I took a quick look. Some thoughts:
- The wording/example on the README makes it confusing to show that 'service' is optional and is now auto discovered to match the bundle id. Some clarification and a more explicit example would be good. Also, might break for existing users?
- I don't know if auto discovering the group is desired... I would assume one should always want explicit group permission when saving sensitive data. Not 100% sure about this though, but I always go for explicit APIs as implicit internal behavior is hard to debug if something goes wrong. If the group is there I always now I'm writing a value that can be read/written by the group. Therefore I would get rid of implicit group discovery.
- Same goes for the auto discovering of the
service, but here I'm just worried if it will break compatibility with the existing users of the library. Not sure what is the default behavior is service is missing, it should default to the bundle id no? - I agree with the error throwing about the params. Everything should be returned in the
errorfield instead of throwing exceptions, including the param errors. This was an oversight on my part. Can you take care of it in a following PR and will release it in a single go.
Review asked for explicit access groups: an omitted accessGroup now leaves kSecAttrAccessGroup out of the query, as before, and the probe item that discovered the default group is removed. The discovered group could change when entitlements changed, hiding items saved earlier, and the probe failed before the first unlock. Invalid or unconvertible service and accessGroup values still return an error. Note: inkdrop://note/s2IGKjCd
|
Hi @ospfranco !
I recently came across your library, and it looks great for storing access keys for my app.
I found that it doesn't support service or accessGroup for iOS yet, so I added them. It allows apps to access the keychain items from share extensions.
Here is a description my agent wrote:
Add
serviceandaccessGroupoptions (iOS)Adds optional
serviceandaccessGroupparams toset,getanddel. With them, a Keychain item can be shared with an app extension (for example a share extension) through a Keychain access group or an app group.Changes
ios/bindings.mm):get_base_entry_dictnow takes anItemScope.servicesetskSecAttrServiceand defaults to the bundle identifier, as before.accessGroupsetskSecAttrAccessGrouponly when given.set(including its delete-before-add step),getanddel.setreturns{ error }, andget/delthrow.accessibilityis, because items are always private to the app.ItemScopeinterface and used it in the set/get/del params and the native param types.accessGroupis omitted,get,deland the replace step insetmatch the key in every access group the app belongs to, the same as the Keychain API itself.stringToNSStringnow builds from the byte length, so an embedded NUL no longer truncates the value. A nil bundle identifier no longer crashes.Backward compatibility
If you pass neither option, nothing changes: same service, default access group, and existing items are still readable.
Tests
New cases in
example/src/tests/s2.ts:[op-s2] Missing entitlement.All tests pass on an iOS 26.5 simulator and an Android API 36 emulator, both Release builds.
Note
on the iOS 27 simulator, the example app crashes at launch in
_UIApplicationEvaluateRuntimeIssueForNoSceneLifecycleAdoption, because it hasn't adopted the UIScene lifecycle. This is unrelated to this PR.Feel free to discard the PR and implement it in your own way 🙏