Access to a keychain item's password via Security framework is lost if a user enters the wrong password once (rdar://50789571)

Summary


If a user enters the wrong password, when they are asked for their macOS user credentials to access the password of a keychain item, and press "Do not allow" when asked again, the following happens:


  • programmatic access to the keychain item's password using
    SecItemCopyMatching
    consistently fails with error OSStatus
    -25293
    , yet the user is never prompted to enter their macOS credentials
  • programmatic access to the password of any keychain item of the same keychain fails with error
    -25293
  • the user is not asked for their credentials again until they manually lock and unlock the login keychain (or any custom keychain the keychain item belonged to) in Keychain Access.app (or perform an action which locks and unlocks the keychain, like log out or restart of macOS)


WARNING: After trying to reproduce this problem, iMessage will no longer work and no new keychain items can be added until the login keychain is locked/unlocked manually

A custom script using the Security.framework keychain API's is available, but for most basic steps to reproduce the "security" command line utility is used.

While I really don't think this is expected behavior, I'd be interested to learn more.



Steps to Reproduce:


1.) Create a login keychain item for the test


security add-generic-password -l "Keychain Bug Test Item" -a "AccessToKeychainItemsPasswordIsLostRdar" -s "keychain-bug" -T "" -w "supersecurepassword"

2.) Try to access the test keychain item.


security find-generic-password -a "AccessToKeychainItemsPasswordIsLostRdar" -w

When presented with the authentication dialog, enter your macOS credentials. -> the password "supersecurepassword" is displayed in Terminal


3.) Try to access the test keychain item, but fail on purpose


security find-generic-password -a "AccessToKeychainItemsPasswordIsLostRdar" -w

This time, when presented with the authentication dialog, make sure to enter the wrong credentials and press "Allow". After being asked for your password a second time, press "Don't allow"


3.) Try to access the test keychain item again


security find-generic-password -a "AccessToKeychainItemsPasswordIsLostRdar" -w

You will notice that the command exits without displaying the password and without ever presenting an authentication dialog. Test if you are able to send a message in iMessage. That will no longer work.


In my tests, even keychain item's which "Allow any application to access this item without warning" were no longer able to retrieve the password



Expected Results:


As before entering the wrong credentials, the user should simply be presented with an authentication dialog again. At the moment, they are not informed of any problem, yet won't be able for example in iMessage to send messages. The bug will show different symptoms in different applications, depending what keychain access is used for.


Actual Results:


The user is never prompted for entering their credentials again. Applications fail to work properly in different way.


Version/Build:

macOS 10.14.3 (18D109), macOS 10.14.4

Replies

I thought I’d try this out for myself, so I spun up a fresh 10.14.4 VM and ran your first two commands:

$ security add-generic-password -l "Keychain Bug Test Item" -a "AccessToKeychainItemsPasswordIsLostRdar" -s "keychain-bug" -w "supersecurepassword"  
$ security find-generic-password -a "AccessToKeychainItemsPasswordIsLostRdar" -w
supersecurepassword

Based on your description, I was expecting to see an authorisation dialog after entering the second command. I did not. Rather, the

security
tool printed the password without any user interaction.

Which, btw, is what I would have expected before reading your post. The item was created by the

security
tool and thus its ACL is set to allow unfettered access by that tool.

I suspect I’m missing some critical step here.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Indeed, I didn't notice that I forgot one crucial step. I will update it here, and create a new rdar://

The first step where we create a new keychain item has to be created with -T "" so that

security
is not added to the list of applications which are always allowed to access the item without warning.


In the meantime I also found out that this bug is even more sever than original assumed, since after triggering it, it is no longer possible to add any keychain item to the keychain the test keychain item belongs to.


(Only system keychain item don't show this behavior).


So the amended step 1 should read:


security delete-generic-password -a "AccessToKeychainItemsPasswordIsLostRdar"
security add-generic-password -l "Keychain Bug Test Item" -a "AccessToKeychainItemsPasswordIsLostRdar" -s "keychain-bug" -T "" -w "supersecurepassword"

(the old entry is first deleted)


After doing that, once you continue with step 2 you will be prompted for your password.


Here the additional steps to confirm, that adding a new keychain item after that is also no longer possible:


security add-generic-password -l "Keychain Bug Test Item 2" -a "AccessToKeychainItemsPasswordIsLostRdar2" -s "keychain-bug-2" -T "" -w "supersecurepassword" security: SecKeychainItemCreateFromContent (): The user name or passphrase you entered is not correct.

What makes this even worse is, querying a keychain item works, as long as you don't ask for the passphrase using kSecReturnData. Also deleting a keychain item still works. Now if you combine these two, two update a keychain item, you have a very problematic result.


Example: Update the password of an existing keychain item:


1.) Check if keychain item "AccessToKeychainItemsPasswordIsLostRdar" exists (no need to set

kSecReturnData
for that) -> item is found, since it does exist and is returned successfully

2.) Since there's an existing keychain item, delete it -> succeeds, as deleting is still possible

3.) Add the new keychain item with new password using

SecItemAdd
-> fails with
-25293 errSecAuthFailed


As a result the original keychain item is now gone and the new one can't be added.


This bug also affects the just released macOS 10.14.5

Were you able to reproduce the issue? Would love to know if I'm doing something wrong or misunderstanding something.

Were you able to reproduce the issue?

I didn’t try, sorry.

Would love to know if I'm doing something wrong or misunderstanding something.

Honestly, if you’re able to mess up the keychain subsystem using just command-line tools, that’s a bug regardless of whether you’re “doing something wrong”.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"