La table access de TCC selon les versions de macOS
L'évolution de la table access de TCC.db de Mojave à Big Sur et Sonoma : allowed, auth_value, auth_reason, pid, last_reminded et les autres tables.
En bref. La table access de TCC.db connaît trois grandes structures. Mojave et Catalina : allowed (0/1) et prompt_count. Big Sur (11) et ultérieur : auth_value, auth_reason et auth_version les remplacent, et indirect_object_identifier devient TEXT NOT NULL DEFAULT 'UNUSED'. Sonoma (14) et ultérieur : ajout de pid, pid_version, boot_uuid et last_reminded. Lancez .schema access sur chaque copie avant de l'interroger. TCC Parser lit les noms de colonnes dans le schéma de chaque fichier, si bien que la même vue fonctionne d'une version à l'autre.
Pourquoi le schéma compte
Requêtes et parseurs échouent sans bruit sur la mauvaise structure. Un script écrit pour Big Sur qui sélectionne auth_value échoue sur une base Catalina ; un script écrit pour Catalina qui filtre sur allowed = 1 ne trouve rien sous Sonoma. Le plugin macostcc de Plaso, par exemple, exige les colonnes allowed et prompt_count d'avant Big Sur : il vise donc les bases de Mojave et Catalina. Le MacOS.System.TCC de Velociraptor a été écrit pour Big Sur. Vérifiez d'abord :
sqlite3 TCC.db '.tables'
sqlite3 TCC.db '.schema access'
Mojave et Catalina (10.14, 10.15)
Tel que documenté par le plugin macostcc de Plaso, la table access comporte :
| Colonne | Notes |
|---|---|
service | Identifiant du service TCC |
client | Bundle ID ou chemin absolu |
client_type | 0 bundle ID, 1 chemin absolu |
allowed | 1 autorisé, 0 non autorisé |
prompt_count | Nombre de fois où une invite a été présentée à l'utilisateur |
csreq | Exigence de code compilée du client |
policy_id | Lien vers policies.id pour les lignes issues d'une politique |
indirect_object_identifier_type, indirect_object_identifier, indirect_object_code_identity | Cible de l'autorisation (Automatisation) |
flags | Non documenté |
last_modified | DEFAULT CAST(strftime('%s','now') AS INTEGER), donc secondes Unix, UTC |
La clé primaire est (service, client, client_type, indirect_object_identifier). Cette clé explique un comportement important : il y a une ligne par client, service et cible, et une nouvelle décision remplace l'ancienne ligne au lieu d'en ajouter une. La base conserve l'état courant, pas un historique.
Big Sur (11) et ultérieur
Big Sur a remplacé allowed et prompt_count par trois colonnes :
| Colonne | Valeurs |
|---|---|
auth_value | 0 refusé, 1 inconnu, 2 autorisé, 3 limité |
auth_reason | Raison de la décision (voir ci-dessous) |
auth_version | Version du format de l'enregistrement d'autorisation |
indirect_object_identifier est devenu TEXT NOT NULL DEFAULT 'UNUSED' : les lignes sans cible contiennent désormais la chaîne littérale UNUSED au lieu d'une valeur nulle. Filtrez dessus lorsque vous cherchez des cibles d'Automatisation.
auth_reason
Apple ne documente pas ces valeurs. La correspondance ci-dessous est documentée par la communauté et largement utilisée ; lisez-la comme une hypothèse et confirmez-la sur un Mac de test de la même version, ou à partir des entrées com.apple.TCC du journal unifié, avant de la reprendre dans un rapport.
| auth_reason | Interprétation de la communauté |
|---|---|
| 1 | Erreur |
| 2 | Consentement de l'utilisateur (réponse à une invite) |
| 3 | Défini par l'utilisateur (modifié dans les Réglages Système) |
| 4 | Défini par le système |
| 5 | Politique de service |
| 6 | Politique MDM |
| 7 | Politique de remplacement |
| 8 | Chaîne d'usage manquante |
| 9 | Délai d'invite dépassé |
| 10 | Preflight inconnu |
| 11 | Entitlement |
| 12 | Politique par type d'app |
La distinction utile dans la plupart des cas oppose les raisons liées à l'utilisateur (2, 3), celles liées à une politique (5, 6, 7) et celles liées au système (4, 11, 12). Glossaire : auth_value, auth_reason.
Sonoma (14) et ultérieur
Sonoma a ajouté quatre colonnes :
| Colonne | Notes |
|---|---|
pid | Un identifiant de processus associé à la ligne |
pid_version | Accompagne pid |
boot_uuid | Identifie une session de démarrage |
last_reminded | Secondes d'époque Unix ; valeur par défaut du schéma strftime('%s','now') |
Les noms évoquent le processus et la session de démarrage impliqués dans la décision, mais leur sémantique exacte n'est pas documentée publiquement. boot_uuid reste pratique : il permet de regrouper les lignes par session de démarrage et de les comparer avec d'autres artefacts qui enregistrent un UUID de démarrage. last_reminded est un second horodatage à placer sur la chronologie ; dans TCC Parser, vous pouvez basculer le champ de temps entre Last modified (dernière modification), Last reminded (dernier rappel) et Expired at (expiration).
Versions plus récentes
Nous n'avons connaissance d'aucune documentation publique de changements du schéma d'access après Sonoma, macOS 26 Tahoe compris. C'est précisément pour cette raison que TCC Parser s'appuie sur le schéma : il lit la liste des colonnes de chaque fichier et décode celles qu'il reconnaît, au lieu de supposer une structure fixe par version. Si vous rencontrez une colonne que cet article ne mentionne pas, vérifiez-la sur un système de test avant de l'interpréter.
Les autres tables
La table access concentre toute l'attention, mais la base contient davantage. Dans le schéma Mojave/Catalina documenté par Plaso :
| Table | Colonnes | À quoi elle sert |
|---|---|---|
admin | key, value | Petit magasin clé/valeur ; contenu non documenté |
policies | id, bundle_id, uuid, display | Politiques référencées par access.policy_id (par exemple MDM) |
active_policy | client, client_type, policy_id | Quelle politique s'applique à quel client |
access_overrides | service (clé primaire) | Remplacements par service ; rôle non documenté |
expired | service, client, client_type, csreq, last_modified, expired_at | Autorisations expirées, avec l'heure de leur expiration |
Listez les tables de votre propre copie avec .tables : les versions ultérieures peuvent différer. La table expired mérite un examen dans chaque dossier, car elle conserve des clients qui n'apparaissent plus dans access. Son expired_at est en secondes Unix, comme last_modified. TCC Parser relie policy_id à la table policies et à MDMOverrides.plist, et affiche REG.db ainsi que tout autre fichier SQLite trouvé dans le dossier com.apple.TCC sous forme de tables brutes.
Une requête par structure
Mojave et Catalina :
SELECT service, client, client_type, allowed, prompt_count,
datetime(last_modified, 'unixepoch') AS changed_utc
FROM access ORDER BY last_modified DESC;
Big Sur et ultérieur (ajoutez last_reminded à partir de Sonoma) :
SELECT service, client, client_type, auth_value, auth_reason,
NULLIF(indirect_object_identifier, 'UNUSED') AS target,
datetime(last_modified, 'unixepoch') AS changed_utc
FROM access ORDER BY last_modified DESC;
Les deux renvoient les blobs (csreq, indirect_object_code_identity) sous forme d'octets bruts ; leur décodage est traité dans décoder les exigences de code csreq dans TCC.db.
Horodatages
Tous les horodatages de TCC.db sont en secondes d'époque Unix, UTC : last_modified, last_reminded et expired.expired_at. Ce n'est pas du temps absolu Mac, qu'utilisent de nombreuses autres bases Apple. last_modified correspond à la dernière écriture de la ligne : une invite validée, un interrupteur basculé, une politique appliquée. Ce n'est pas la première autorisation.
Questions fréquentes
Quelle version de macOS a remplacé allowed par auth_value dans TCC.db ?
macOS 11 Big Sur. Les bases de Mojave et Catalina ont des colonnes allowed et prompt_count ; à partir de Big Sur, elles sont remplacées par auth_value, auth_reason et auth_version.
Quelles colonnes Sonoma a-t-il ajoutées à la table access ?
macOS 14 Sonoma a ajouté pid, pid_version, boot_uuid et last_reminded. last_reminded est en secondes d'époque Unix, comme last_modified.
Les valeurs d'auth_reason sont-elles documentées par Apple ?
Non. La correspondance couramment utilisée (1 erreur, 2 consentement de l'utilisateur, 3 défini par l'utilisateur, 4 défini par le système, 5 politique de service, 6 politique MDM, 7 politique de remplacement, 8 chaîne d'usage manquante, 9 délai d'invite dépassé, 10 preflight inconnu, 11 entitlement, 12 politique par type d'app) provient de recherches de la communauté. Confirmez-la sur un système de test avant de vous appuyer dessus.
Pourquoi ma requête échoue-t-elle sur une TCC.db plus ancienne ?
Parce que la colonne sélectionnée n'existe pas dans ce schéma. Lancez d'abord .schema access et écrivez la requête pour les colonnes réellement présentes.