Un article complémentaire a introduit la dérive du moindre privilège sous le nom de gap entre ce qu’un agent d’IA est autorisé à faire et ce qu’il est observé en train de faire. Cet article couvrait le concept : pourquoi le gap se forme, comment l’observation en lecture en premier produit une différence autorisée/observée et comment la politique en tant que code la ferme au moment de l’accès. Cet article va encore plus loin : il explique comment la dérive devient une découverte structurée, classifiée et triable à l’intérieur du module de sécurité, et ce qui lui arrive une fois qu’elle existe.
La version courte : la dérive n’est pas une métrique de tableau de bord ni une ligne de journal. Il s’agit d’une entité persistante avec une classification, une gravité, un niveau de confiance et un cycle de vie de tri. Il alimente la file d’attente des anomalies, enrichit les délais médico-légaux et est honnête sur ce qu’il peut et ne peut pas prouver.
Les trois sources de signaux
Chaque bord de la carte d’accès enregistre une relation d’accès entre une origine (un agent, une identité, une session) et une ressource. Chaque arête porte deux indicateurs booléens : Autorisé et Observé. Les bords intéressants sont ceux sur lesquels ces drapeaux ne sont pas d’accord.
Mais les drapeaux ne viennent pas de nulle part. Ils proviennent de sources de signaux distinctes, chacune avec un profil de confiance différent :
Politique (autorisée). Un dispositif Edge avec signal_source=policy ou signal_source=scoped_grant représente une autorisation déclarée : quelque chose qu’un identifiant, un rôle IAM ou le propre plan de portée source de la plateforme indique que cet agent est autorisé à faire. Ces bords sont permitted=true, observed=false jusqu’à ce que la télémétrie les corrobore. Ils sont le plafond. Les connecteurs d’identité (émetteurs WIF, rosters de clés API, rôles d’espace de travail) alimentent ce côté. Un compte de service fédéré autorisé à utiliser la portée OAuth de sa règle dans un espace de travail est l’un de ces avantages.
Télémétrie (observée). Signaux coopératifs provenant des traces OpenTelemetry, des journaux pgAudit, des enregistrements CloudTrail, des annotations MCP, des observations du protocole A2A et des webhooks GitHub/GitLab. Ceux-ci produisent des bords où observed=true. Leur confiance dépend de la source : une classification pgAudit READ est attributed (la base de données sait qui a interrogé et s’il s’agit d’une lecture ou d’une écriture) ; un MCP readOnlyHint est approximate par spécification - la spécification MCP elle-même indique que les annotations d’outils ne sont pas fiables.
Noyau (vérité terrain). Le backstop eBPF (signal_source=ebpf) observe au niveau de l’appel système. C’est le signal qu’un agent ne peut pas contourner. Lorsque la couche eBPF détecte un connect() ou un write() que la télémétrie coopérative n’a pas signalé, il ne s’agit pas d’un gap de journalisation : il s’agit d’un signal anti-évasion. Le module de sécurité réunit les observations côté noyau et côté coopératif dans une anomalie corrélée, de sorte qu’un agent qui fait taire sa propre télémétrie devient une découverte et non un angle mort.
La carte d’accès est une requête sur ces bords, et non un schéma distinct. La dérive du moindre privilège est le sous-ensemble dans lequel les deux drapeaux sont en désaccord.
Comment la dérive devient une découverte
Un désaccord entre Permitted et Observed est le signal brut. Le moteur le classe dans l’un des deux types de dérive avant qu’il n’entre dans la file d’attente des anomalies :
// DriftKind classe une dérive de moindre privilège entre autorisée et observée.
type DriftKind string
const (
// DriftUnusedGrant est un accès autorisé jamais observé (surprovisionné).
DriftUnusedGrant DriftKind = "unused_grant"
// DriftViolation est un accès observé qui n’est pas autorisé.
DriftViolation DriftKind = "violation"
)
unused_grant signifie qu’une stratégie indique que l’agent peut faire quelque chose qu’il n’a jamais vu faire. Il s’agit d’un privilège mort – un risque porté sans bénéfice. C’est le signal de nettoyage pour les révisions d’accès périodiques : révoquer ce qui n’est pas exercé.
violation signifie que l’agent a été observé en train de faire quelque chose qu’aucune politique ou autorisation ne permet. C’est la découverte active. C’est la ligne de la table de comparaison qui indique « écriture non révisée » – le bord qui compte, celui que la file d’attente d’anomalies donne la priorité.
La classification n’est pas binaire entre « bien » et « problème ». La structure PrivilegeDrift associe le bord incriminé à son type :
// PrivilegeDrift est un écart de moindre privilège : une arête dont les indicateurs Permitted
// et Observed ne concordent pas.
type PrivilegeDrift struct {
Edge AccessEdge
Kind DriftKind
}
Le bord lui-même porte la provenance complète : l’origine (quel agent), la ressource, le mode read/write, la source du signal qui l’a produit, la confiance dans l’attribution et la fenêtre d’observation (FirstSeen, LastSeen, OccurrenceCount). Une découverte de dérive n’est jamais « quelque chose ne va pas quelque part ». Il pointe vers un agent spécifique, une ressource spécifique, un mode d’accès spécifique, observé par un collecteur spécifique, avec une plage horaire.
La file d’attente des anomalies : pas seulement “différentes”, mais classées
Lorsque le module de sécurité crée la vue des anomalies (le point de terminaison GET /v1/m/security/anomalies), il extrait la dérive du magasin de périphérie d’accès et classe chaque violation dans une anomalie prioritaire. La classification ajoute un contexte que le bord brut ne contient pas :
Dérive d’accès. La ligne de base : un accès observé mais non autorisé. L’anomalie est intitulée « Accès inattendu : observé mais non autorisé », de gravité moyenne, et marquée avec confidence=approximate car la dérive au niveau du magasin est le signal brut — pas encore rapproché du graphique complet agent-identité. La vue réconciliée réside dans le propre point de terminaison /drift de la carte d’accès ; la file d’attente d’anomalies consomme le signal brut et l’étiquete honnêtement.
Egress/exfiltration suspecté. Lorsque la ressource sur le bord de dérive est un point de terminaison de réseau vers une destination externe non privée (le connecteur eBPF les émet en tant qu’URI tcp://host:port), l’anomalie est reclassée en egress_exfil_suspected et promue au niveau de gravité élevé. Un agent écrivant sur un point de terminaison externe auquel il n’a jamais eu accès constitue une forme de recherche différente de celle d’un agent lisant une table de base de données pour laquelle il n’a pas été autorisé.
Augmentation de sensibilité. Lorsque la ressource porte une étiquette de sensibilité (high ou secret), la gravité est promue, que l’accès soit une sortie ou non. Un violation sur une ressource hautement sensible garantit un tri plus rapide même si la destination est interne.
Chaque anomalie porte une carte evidence avec les détails bruts :
ev := map[string]any{
"origin_kind": edge.OriginKind,
"origin_id": edge.OriginID.String(),
"resource_id": edge.ResourceID.String(),
"mode": string(edge.Mode),
"signal_source": string(edge.SignalSource),
"occurrence_count": edge.OccurrenceCount,
"reconciled": false,
}
Le reconciled: false est délibéré. Il indique au consommateur qu’il s’agit du signal brut au niveau du magasin, et non de la vue rapprochée de l’agent à l’identité de la carte d’accès. La file d’attente des anomalies n’attend pas la réconciliation pour faire apparaître un violation – mais elle ne prétend pas que l’attribution est ferme alors qu’elle ne l’est pas.
Niveaux de confiance : que peut-on prouver
Chaque bord de la carte d’accès comporte un niveau de confiance. Le produit en utilise deux :
-
Attribué (
confidence=attributed) : l’accès est fermement lié à l’origine par les propres preuves du collectionneur. Un enregistrement pgAudit nommant le rôle de base de données de l’agent, un événement CloudTrail lié aux informations d’identification IAM de l’agent, une observation eBPF liée à un ID de processus que le runtime a résolu en un agent. La chaîne d’attribution est de bout en bout. -
Approximativement (
confidence=approximate) : l’attribution est déduite et peut entraîner une perte. Le signal provenait d’un compte de service partagé où plusieurs agents utilisent les mêmes informations d’identification, d’un magasin avec perte (une instance Redis qui n’enregistre pas l’identité par connexion) ou d’une annotation MCP qui, selon la spécification, n’est pas fiable. Le front est toujours un signal, mais l’opérateur sait que la preuve est plus faible.
Le niveau de confiance affecte le score de priorité de l’anomalie. La fonction de priorité (priorityFor) note chaque anomalie de 0 à 100, et une dérive de confiance approximate est ignorée :
if confidence == string(sdkmodel.ConfidenceApproximate) {
// remise : la dérive non réconciliée est bruyante
}
Cela empêche un signal d’identité partagée bruyant de repousser fermement un attributed violation. Les deux apparaissent dans la file d’attente ; le approximate se classe plus bas. C’est le même principe que celui appliqué par l’enrichissement médico-légal : lorsqu’une identité partagée (SharedIdentity: true, AgentCount > 1) est trouvée, la chronologie indique que “l’attribution par agent peut être ambiguë” plutôt que de prétendre que l’attribution est exacte.
Le produit ne simule jamais la certitude. Une arête MCP réservée aux annotations n’a pas le même poids qu’une arête corroborée par eBPF. Un résultat de dérive provenant d’un compte de service partagé n’a pas le même poids qu’un résultat provenant d’une identité par agent. L’opérateur voit la différence et effectue le tri en conséquence.
Dérive dans la chronologie médico-légale
Les découvertes de dérive n’existent pas uniquement dans la file d’attente des anomalies. Lorsqu’un dossier médico-légal est ouvert et que sa chronologie est reconstruite à partir du grand livre d’audit chaîné par hachage, le module de sécurité enrichit la reconstruction avec la dérive du sujet :
out.Drift = subjectDrift(r.Context(), sc, c.SubjectRef)
La fonction subjectDrift interroge le magasin Edge d’accès pour la dérive du genre violation où le sujet est l’origine, et renvoie une liste d’entrées driftRefDTO, chacune contenant l’origine, la ressource, le mode d’accès, la source du signal, le nombre d’occurrences et l’horodatage de la dernière visualisation. Ceux-ci sont lus à partir du propre calcul de dérive du magasin, non recalculés par le module de sécurité.
La chronologie comporte également l’attribution de l’identité du sujet et la traçabilité des données, de sorte qu’un enquêteur examinant un cas ait une vue d’ensemble : qui agit l’agent (et si cette identité est partagée), à quoi il a accédé et qu’il n’aurait pas dû avoir, et de quelles données il a tiré des réponses. Chacun de ces enrichissements tolère les voisins absents : si le module de connaissances n’est pas installé, la lignée est omise plutôt que falsifiée ; si l’identité n’a pas de liaison d’agent résolue, l’attribution dit « pas encore lié » plutôt que d’en inventer une.
Le cycle de vie du triage
Une découverte provenant d’une dérive entre dans le système avec le statut open. À partir de là, il suit le cycle de vie standard du tri des résultats :
- ouvert : le résultat existe, personne n’a encore donné suite.
- trié : un opérateur l’a reconnu et l’a assigné pour examen.
- résolu : la cause sous-jacente a été corrigée (la subvention a été révoquée, la politique a été renforcée, l’agent a été redéfini).
- rejeté : l’opérateur l’a examiné et a déterminé qu’il ne s’agit pas d’un risque réel (un comportement connu, un faux positif d’attribution approximate).
Chaque changement d’état de triage est auto-audité par le véritable principal. Le fait de rejeter une constatation est lui-même enregistré dans le registre inviolable, de sorte qu’un auditeur peut voir non seulement quelle dérive s’est produite, mais aussi qui l’a examiné et quelle a été sa décision. Les preuves de la découverte (sa nature, leur gravité et leur hachage détaillé) sont immuables après leur création ; le triage modifie uniquement l’état du flux de travail.
Ce que cela signifie en pratique
Un agent reçoit une clé API limitée à un espace de travail Claude. Le connecteur d’identité lit la liste de l’espace de travail et émet une stratégie : cette clé est autorisée à appeler l’API dans cet espace de travail. L’agent fonctionne pendant trois semaines. La télémétrie le montre en train d’appeler l’API dans cet espace de travail – pas de dérive. Ensuite, une modification de déploiement donne à l’agent l’accès à la clé d’un deuxième espace de travail. La télémétrie observe l’agent appelant les deux espaces de travail. Le deuxième espace de travail n’a aucun avantage politique. Un constat de dérive du type violation est créé : observé mais non autorisé. Il entre dans la file d’attente des anomalies sous le nom access_drift, gravité moyenne, confiance approximate (le bord n’a pas encore été rapproché du graphique d’identité). Si la ressource dans le deuxième espace de travail porte une étiquette de sensibilité high, la gravité est favorisée. Le résultat reste dans la file d’attente de l’opérateur jusqu’à ce que quelqu’un le trie.
C’est la différence entre l’enregistrement et la dérive structurée : les résultats sont classés, attributed (avec une confiance honnête), hiérarchisés et triables. Il persiste jusqu’à ce que quelqu’un le résolve ou le rejette. Il apparaît dans la chronologie médico-légale si l’agent fait ultérieurement l’objet d’un cas d’incident. Et chaque action entreprise est enregistrée dans une chaîne dont le produit peut prouver l’intégrité.
La dérive n’est pas une mesure à minimiser. C’est une constatation à trier. Le gap entre ce qu’un agent est autorisé à faire et ce qu’il est observé en train de faire constitue la surface de signal la plus élevée pour l’application du moindre privilège - mais seulement lorsque le gap est structuré, classifié et honnête quant à ce qu’il peut prouver.
Pour voir la carte d’accès et la surface de dérive sur un domaine roulant, visitez la page produit de la carte d’accès ou la présentation du produit.