IMPORTANT: The information outlined below might give you just enough rope to hang yourself. I take no responsibility for the accuracy of the information in this post, or for any damage you cause while relying on it.

Partial screenshot of System Settings showing stale and duplicate entries.

TCC (Transparency, Constent, and Control) is how macOS manages the permissions requested by apps and granted by users to things like the microphone, location, application control, and more.

I just spent the last couple hours trying to clean up the mess left behind while working on one of my current macOS app projects. Because the app installs a CGEventTap, it requires “Accessibility” permission from the user (System Settings -> Privacy & Security -> Accessibility). In order to test new user flows, I needed to be able to reset those settings. Compounding the problem, I had changed the name of the app a few times, and had several, even duplicate, entries for it.

To be clear, these are problems caused by Apple’s poor design, implementation, and documentation of TCC.

macOS stores TCC user consent in a few places on disk:

  • /Library/Application Support/com.apple.TCC/
  • /Users/*/Library/Application Support/com.apple.TCC/
  • Perhaps others, but not on my machine (macOS 14.2)

Inside those directories is TCC.db, a SQLite database, and a directory AdhocSignatureCache. This directory contains a number of “Mac OS X Detached Code Signature” files with UUID strings for names, and a file named keys.

Using tccutil

Generally, you delete entries using tccutil:

% sudo tccutil reset All com.exmaple.AppBundleID
Password: 
Successfully reset All approval status for com.exmaple.AppBundleID
Successfully reset All approval status for com.exmaple.AppBundleID
Successfully reset All approval status for com.exmaple.AppBundleID

It always seems to print three lines, even if I repeat the command.

In this example, “All” refers to all services to which the app may have been granted permission.

Unfortunately, if the app bundle itself no longer exists on the disk, you’ll get an error:

% sudo tccutil reset All com.exmaple.MissingAppBundleID
Password: 
tccutil: No such bundle identifier "com.exmaple.MissingAppBundleID": The operation couldn’t be completed. (OSStatus error -10814.)

And the entry will remain in the TCC.db file (and System Settings will show an entry for the app).

Using SQLite

The TCC registry is a SQLite DB. You can modify this DB directly, but you must first disable System Integrity Protection (SIP).1

Once you’ve done that, you can list entries for an app like this:

% sudo sqlite3 /Library/Application\ Support/com.apple.TCC/TCC.db
sqlite> select * from access where client like '%Daisy%';
service                          client                                client_type  auth_value  auth_reason  auth_version  csreq  policy_id  indirect_object_identifier_type  indirect_object_identifier  indirect_object_code_identity  flags  last_modified  pid  pid_version  boot_uuid  last_reminded
-------------------------------  ------------------------------------  -----------  ----------  -----------  ------------  -----  ---------  -------------------------------  --------------------------  -----------------------------  -----  -------------  ---  -----------  ---------  -------------
kTCCServiceSystemPolicyAllFiles  com.daisydiskapp.DaisyDiskStandAlone  0            0           5            1             ??                                                 UNUSED                                                     0      1641727294                       UNUSED     0            

This shows that DaisyDisk has been granted “Full Disk Access” permission. To remove it, do this:

sqlite> delete from access where client = 'com.daisydiskapp.DaisyDiskStandAlone';
sqlite> ^D

Once you’ve removed the stale entries, don’t forget to re-enable SIP!

When You Can’t Find the Entry

If you can’t find the entry for your app, but it’s still showing up in System Settings, be aware that sometimes macOS writes the client value as a path to the application binary. In my case, it was like this:

sqlite> select * from access where client like '%ReKey%';
service                   client                                                        client_type  auth_value  auth_reason  auth_version  csreq  policy_id  indirect_object_identifier_type  indirect_object_identifier  indirect_object_code_identity  flags  last_modified  pid  pid_version  boot_uuid  last_reminded
------------------------  ------------------------------------------------------------  -----------  ----------  -----------  ------------  -----  ---------  -------------------------------  --------------------------  -----------------------------  -----  -------------  ---  -----------  ---------  -------------
kTCCServicePostEvent      /Users/me/Library/Developer/Xcode/DerivedData/ReKey-dmirb  1            2           4            2             ??                0                                UNUSED                                                     0      1696485626                       UNUSED     0            
                          tqbnbsehigusolzjwvezofn/Build/Products/Debug/ReKeyAgent                                                                                                                                                                                                                                         

kTCCServicePostEvent      /Users/me/Library/Developer/Xcode/DerivedData/ReKey-dmirb  1            2           4            2             ??                0                                UNUSED                                                     0      1696489748                       UNUSED     0            
                          tqbnbsehigusolzjwvezofn/Build/Products/Debug/ReKey.app/Conte                                                                                                                                                                                                                                    
                          nts/Resources/ReKeyAgent                                                                                                                                                                                                                                                                        

kTCCServicePostEvent      /Users/me/Library/Developer/Xcode/DerivedData/ReKey-dmirb  1            2           4            2             ??                0                                UNUSED                                                     0      1697670395                       UNUSED     0            
                          tqbnbsehigusolzjwvezofn/Build/Products/Debug/ReKey Helper                                                                                                                                                                                                                                       

kTCCServicePostEvent      /Users/me/Library/Developer/Xcode/DerivedData/ReKey-dmirb  1            2           4            2             ??                0                                UNUSED                                                     0      1698656027                       UNUSED     0            
                          tqbnbsehigusolzjwvezofn/Build/Products/Debug/ReKey.app/Conte                                                                                                                                                                                                                                    
                          nts/Resources/ReKey Helper                                                                                                                                                                                                                                                                      

kTCCServiceAccessibility  /Users/me/Library/Developer/Xcode/DerivedData/ReKey-dmirb  1            2           4            1             ??                0                                UNUSED                                                     0      1698656027                       UNUSED     0            
                          tqbnbsehigusolzjwvezofn/Build/Products/Debug/ReKey.app/Conte                                                                                                                                                                                                                                    
                          nts/Resources/ReKey Helper                                                                                                                                                                                                                                                                      

And this was the source of the double duplicate entries I was seeing.

The Other Files

The steps above are probably sufficient to clean up TCC and System Settings. But if you’re still seeing evidence of the apps, consider removing the appropriate AdhocSignatureCache files.

I found the right ones by using The Silver Searcher (installed via brew):

% cd /Library/Application\ Support/com.apple.TCC/
% ag -o --search-binary ReKey                 
Binary file AFC61784-3BE7-4FD5-93EE-48F4AC98B24E matches.

Binary file D69EDEE2-AF52-4286-831D-F3B130689394 matches.

Binary file F81364ED-F9A6-4B84-B0DC-37C464FB89AE matches.

The keys file is a Plist (NSKeyedArchiver serialization). It’s probably not wise to edit this file. Before thinking it through, I deleted some array entries that were paths to my missing binaries. I haven’t noticed any adverse result from doing this, but I don’t know enough about NSKeyedArchiver to know if I screwed up some internal references or not.

Final Notes

These kinds of edits are not for the feint of heart. I take no responsibility for the accuracy of the information in this post, or for any damage you cause while relying on it.

To make any chances to TCC files, you must disable SIP. Don’t forget to reenable it when you’re done with your edits.

And it’s probably a good idea to make backup copies of the files before you edit or delete them.

If you do somehow screw things up, try using tccutil reset to reset all permissions. You’ll have to re-enable them for all your apps as you encounter them, but it should solve any issues (note, I have not tried this myself).

Resources

I learned all this through experimentation and some information found online:

  • https://eclecticlight.co/2023/02/12/last-week-on-my-mac-children-animals-and-tcc/