.LastGKReject : les rejets Gatekeeper comme preuve
Ce que .LastGKReject enregistre quand Gatekeeper bloque un élément, où le trouver, comment le collecter et le relier au téléchargement d’origine.
TL;DR. Quand Gatekeeper refuse d’exécuter un élément, syspolicyd écrit une petite liste de propriétés nommée .LastGKReject. Elle contient un signet (bookmark) vers l’élément rejeté, dont on peut extraire le chemin cible et le volume, un TimeStamp et un nombre XProtectMalwareType. Seul le dernier rejet est conservé et le fichier peut ne pas exister du tout, mais lorsqu’il est présent, il transforme un téléchargement mis en quarantaine en une tentative de lancement concrète, datée et bloquée par macOS.
Ce que vérifie Gatekeeper
Gatekeeper est implémenté par le démon syspolicyd. Au premier lancement d’un code en quarantaine, il vérifie la signature du code, la présence d’une signature Developer ID, la notarisation, et il exécute XProtect. Le lien avec le reste de cette série est l’attribut de quarantaine : les contrôles sont déclenchés par la valeur com.apple.quarantine que l’application de téléchargement ou l’Utilitaire d’archive a laissée sur le fichier. Le guide des flags détaille cette valeur.
Deux issues laissent des traces. Si l’utilisateur approuve un élément, l’attribut reçoit le flag d’approbation utilisateur 0x0040 : une valeur comme 0083 devient 00c3. Depuis macOS 15, l’ancien contournement par Contrôle-clic a disparu et les dérogations passent par Réglages Système. Si Gatekeeper refuse l’élément, syspolicyd consigne l’échec dans .LastGKReject.
Ce qu’est .LastGKReject
.LastGKReject est une liste de propriétés, XML ou binaire, écrite par syspolicyd lorsque Gatekeeper refuse un élément. Dans le code open source Security d’Apple, c’est PolicyEngine::recordFailure qui l’écrit. Deux propriétés déterminent la façon de le lire :
- Seul le dernier rejet est conservé. Chaque nouveau rejet remplace l’enregistrement précédent.
- Il peut ne pas exister. Un Mac sur lequel Gatekeeper n’a jamais rien refusé, ou sur lequel le fichier a été supprimé, n’en a tout simplement pas.
Le fichier peut aussi exister et être vide. Sur un système macOS 26.6 examiné en direct, /private/var/db/.LastGKReject était absent, tandis que /private/var/db/SystemPolicyConfiguration/.LastGKReject existait sous la forme d’une liste de propriétés XML de 181 octets, lisible par tous, contenant un dictionnaire vide. Quarantine Parser signale ce cas par « aucun rejet enregistré ». Il s’agit d’une observation sur un seul système, pas d’une règle documentée.
Où il se trouve
Les sources d’Apple indiquent deux emplacements ; vérifiez les deux :
| Source | Chemin |
|---|---|
| Sources Apple anciennes | /var/db/.LastGKReject (= /private/var/db/.LastGKReject) |
| Sources Apple actuelles | /var/db/SystemPolicyConfiguration/.LastGKReject |
Les deux se trouvent dans des répertoires système : leur lecture nécessite root.
Les clés
Le plugin QUARANTINE de mac_apt lit trois clés, et Quarantine Parser lit les mêmes informations :
- BookmarkData — un signet vers l’élément rejeté. Un signet est une référence de fichier sérialisée, pas une simple chaîne de chemin ; l’outil en extrait le chemin cible et le volume.
- TimeStamp — le moment où le rejet a été enregistré.
- XProtectMalwareType — un nombre. mac_apt attribue cette correspondance à Patrick Wardle : 2 app/programme non signé, 3 bundle modifié, 5 app signée, 7 app modifiée. Cette correspondance est rapportée, pas documentée par Apple.
Lisez XProtectMalwareType comme une catégorie de refus, pas comme un nom de famille de malware. Une valeur 2 indique que l’élément refusé a été signalé comme non signé ; elle ne dit pas ce que fait le code.
Comment le collecter
Sur un Mac allumé, depuis un Terminal disposant de l’accès complet au disque, cette commande du guide de collecte copie celui des deux fichiers qui existe :
for f in /private/var/db/.LastGKReject /private/var/db/SystemPolicyConfiguration/.LastGKReject; do
[ -f "$f" ] && sudo cp -p "$f" ~/qcase/"$(basename "$(dirname "$f")")_LastGKReject"
done
Les copies portent le nom de leur répertoire parent (db_LastGKReject ou SystemPolicyConfiguration_LastGKReject), ce qui permet de savoir de quel emplacement provient chacune. Lancez-la après avoir créé ~/qcase et copié la base de quarantaine, comme le montre la comparaison des outils de collecte. Calculez les empreintes des copies avant de les analyser.
Sur une image montée, mac_apt analyse à la fois la base de quarantaine et .LastGKReject :
python mac_apt.py -o out MOUNTED /Volumes/evidence QUARANTINE
Dans Quarantine Parser, déposez le fichier copié seul, ou avec la base de données et un listing xattr. L’outil accepte les listes de propriétés XML et binaires, affiche l’heure, le chemin cible, le volume et XProtectMalwareType, et lève une piste rejet Gatekeeper. L’analyse se fait dans votre navigateur ; rien n’est envoyé.
Relier le rejet au téléchargement
À lui seul, .LastGKReject indique qu’un élément a été refusé. Sa valeur vient de sa jonction avec le téléchargement qui l’a apporté. Pour une image disque, la chaîne typique compte trois maillons.
- L’événement de quarantaine. Dans QuarantineEventsV2, vous trouvez le téléchargement de l’image disque : agent, URL et heure. Le guide de la base décrit les colonnes.
- Le volume monté. Monter une image disque en quarantaine place son contenu en quarantaine, et c’est pourquoi l’app qu’elle contient est passée par Gatekeeper. Le chemin rejeté se trouve sous
/Volumes/<nom>/, et le volume lu dans le signet le nomme. - L’app rejetée. Le
TimeStampdoit tomber peu après le téléchargement, et le nom de l’app doit correspondre à l’image.
Dans l’échantillon synthétique du site, la chaîne se présente ainsi :
2026-09-14 10:26:30 UTC QuarantineEventsV2 Safari https://transfer.example/d/Qm7/sync-agent.dmg
2026-09-14 10:27:05 UTC .LastGKReject /Volumes/Sync Agent/SyncAgent.app XProtectMalwareType 2
Trente-cinq secondes séparent le téléchargement du refus, le nom du volume correspond à l’image, et le type rapporté est « app/programme non signé ». Aucune des clés citées plus haut n’est l’UUID de quarantaine : ce lien repose donc sur le nom et l’heure, pas sur un identifiant commun. Écrivez-le dans votre rapport. Le cas d’enquête pas à pas suit le même échantillon de bout en bout.
Si l’élément rejeté existe encore sur le disque, lisez aussi sa valeur com.apple.quarantine. Un flag 00c3 ou 00c1 signifie qu’il a été approuvé ensuite. Un chemin sous /private/var/folders/.../AppTranslocation/ dans d’autres traces signifie qu’une app en quarantaine s’est exécutée depuis un montage aléatoire en lecture seule ; voir App Translocation.
Limites
- Un seul enregistrement. Tout rejet ultérieur, même anodin, écrase celui qui vous intéresse. Collectez tôt.
- Pas d’enregistrement ne veut pas dire rien à signaler. Le fichier peut n’avoir jamais été écrit, ou avoir été supprimé.
- Des libellés non documentés. La correspondance de
XProtectMalwareTypeprovient de recherches tierces. - Un refus n’est pas la fin de l’histoire. L’utilisateur a pu approuver l’élément dans Réglages Système, ou l’attribut de quarantaine a pu être retiré avec
xattr -d com.apple.quarantine, après quoi Gatekeeper n’a plus rien à évaluer. Cherchez le flag 0x0040 et les fichiers qui ont gardé un WhereFroms mais perdu leur attribut de quarantaine, comme l’explique kMDItemWhereFroms face à la quarantaine. - Le signet pointe vers l’emplacement d’origine. Un volume d’image disque disparaît au démontage ; le chemin peut ne plus se résoudre.
- Pas d’URL source. L’enregistrement ne dit pas d’où venait l’élément. C’est le rôle de la base et de l’attribut de quarantaine.
Où chercher ailleurs
- Journaux unifiés. C’est
syspolicydqui réalise l’évaluation : ses entrées de journal autour duTimeStampsont la source suivante naturelle. Elles peuvent montrer des évaluations et des rejets que.LastGKReject, qui ne garde que le dernier, n’a plus. - ExecPolicy. Sur les macOS récents, des fichiers peuvent porter un attribut
com.apple.provenancede 11 octets, une clé opaque vers la tableprovenance_trackingd’ExecPolicy. Ni l’un ni l’autre n’est décodé par Quarantine Parser ; traitez-les comme des pistes pour d’autres outils. - Les données de quarantaine. La ligne d’événement de l’image, l’attribut sur l’image et sur toute copie de l’app, et les enregistrements récupérés dans l’espace libre si une ligne a été supprimée.
Pour une vue d’ensemble de ces artefacts sur une page, consultez la fiche Gatekeeper et XProtect de notre site partenaire.
Questions fréquentes
Le fichier .LastGKReject liste-t-il tous les éléments bloqués par Gatekeeper ?
Non. Il ne conserve que le rejet le plus récent : un rejet ultérieur le remplace. Il peut aussi être totalement absent, et cette absence ne prouve rien sur ce qui a été bloqué ou non.
Où le fichier .LastGKReject est-il stocké ?
Les sources Apple anciennes utilisent /var/db/.LastGKReject (le même fichier que /private/var/db/.LastGKReject) ; les sources Apple actuelles utilisent /var/db/SystemPolicyConfiguration/.LastGKReject. Vérifiez les deux emplacements et copiez le fichier avec les droits root.
Que signifie XProtectMalwareType ?
C’est un nombre stocké dans l’enregistrement. mac_apt, qui en attribue l’origine à Patrick Wardle, indique 2 pour une app ou un programme non signé, 3 pour un bundle modifié, 5 pour une app signée et 7 pour une app modifiée. Apple ne documente pas ces valeurs : considérez le libellé comme une indication, pas comme un verdict.