The weird thing is, SecKeyCreateRandomKey() does create an entry with the correct ACL where only my program can access the key. In all cases I'm creating the ACL simply like so: SecAccessCreate(label as CFString, nil, &acl)
The program should also have a valid code signature, because otherwise macOS doesn't even let it start up. Running from a terminal immediately results in Killed: 9, with the Console program showing an accompanying ASP: Security policy would not allow process, and opening from Finder results in The application “something.app” can’t be opened. And indeed, I do have a Personal Team set in Xcode, it's just not enrolled in the paid developer program. I did also notice that my signed executables actually ran even without updates within a year, so I simply figured that it works because my Personal Team's certificate was still in fact signed by Apple, it just doesn't have access to any restricted entitlements. Since I'm not using those, there's also no provisioning profile to deal with and thus no 7-day limit.
I've actually been using my program for a few years now, I only recently decided to add an export/import function. I currently have a few handfuls of keys in the keychain that were directly created by my program (SecKeyCreateRandomKey()), I deleted one of those (is a test key anyway) and I'm trying to re-import that. During the many recompiles attempting to import, my program could always still access the remaining keys. I'm also using the program on an entirely different Mac that doesn't even have Xcode or any link to my developer account whatsoever, where it also runs without problems even after copying over a new version. Just to confirm, I've recompiled it again and ran codesign --verify --strict --display --verbose=1 on the app bundle:
CodeDirectory v=20500 size=686 flags=0x10000(runtime) hashes=10+7 location=embedded
Signature size=4795
Signed Time=12 Dec 2025 at 19:34:57
Info.plist entries=25
TeamIdentifier=8C3FX9B3SS
And adding --requirements - to the command also lists one designated requirement, which references both the program's bundle ID and my Apple Development certificate. Just to be complete: my program is not sandboxed (prevents some core functionality from working) but I did add the Hardened Runtime capability, for which I haven't enabled any exceptions or resource accesses. For Xcode's Signing Certificate setting I'm using Development (not Sign to Run Locally, which should be the ad-hoc signature). It also shows None Required for Provisioning Profile.
Finally, when checking the ACL of a non-imported key via SecKeychainItemCopyAccess(), I noticed one entry with a lot of hexits that turned out to simply be a plist XML:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Partitions</key>
<array>
<string>teamid:8C3FX9B3SS</string>
</array>
</dict>
</plist>
Same team ID, so partitioning should in fact be working correctly. There's also an entry with 1 trusted apps, and Keychain Access only lists my own program so these should be the same thing. An imported key also shows the partition XML, but all other entries show 0 trusted apps, which does line up with the actual behaviour I'm seeing.
I'll write up a proper bug report for the contradiction sometime later, perhaps tomorrow.
Topic:
Privacy & Security
SubTopic:
General
Tags: