Um post complementar apresentou o desvio de privilégio mínimo como o gap entre o que um agente de IA tem permissão para fazer e o que é observado fazendo. Esse post abordou o conceito: por que o gap se forma, como a observação de leitura primeiro produz uma diferença entre permitido e observado, e como a política como código a corrige no momento do acesso. Este post vai um nível mais profundo — em como o desvio se torna uma constatação estruturada, classificada e passível de triagem dentro do módulo de segurança, e o que acontece com ele uma vez que existe.
A versão resumida: o desvio não é uma métrica de painel ou uma linha de log. Ele é uma entidade persistida com uma classificação, uma severidade, um nível de confiança e um ciclo de vida de triagem. Ele alimenta a fila de anomalias, enriquece cronogramas forenses e é honesto sobre o que pode e não pode provar.
As três fontes de sinal
Cada aresta no mapa de acesso registra uma relação de acesso entre uma origem (um agente, uma identidade, uma sessão) e um recurso. Cada aresta carrega duas bandeiras booleanas: Permitido e Observado. As arestas interessantes são aquelas em que essas bandeiras discordam.
Mas as bandeiras não aparecem do nada. Elas vêm de fontes de sinal distintas, cada uma com um perfil de confiança diferente:
Política (permitida). Uma aresta com signal_source=policy ou signal_source=scoped_grant representa uma concessão declarada: algo que uma credencial, um papel do IAM ou o próprio plano de escopo de origem da plataforma diz que este agente tem permissão para fazer. Essas arestas são permitted=true, observed=false até que a telemetria as corrobore. Elas representam o teto. Os conectores de identidade (emissores WIF, listas de chaves de API, funções de espaço de trabalho) alimentam este lado. Uma conta de serviço federada que tenha permitido o escopo OAuth de sua regra em um espaço de trabalho é uma dessas arestas.
Telemetria (observada). Sinais cooperativos de rastros OpenTelemetry, logs do pgAudit, registros do CloudTrail, anotações MCP, observações do protocolo A2A e webhooks do GitHub/GitLab. Estes produzem conexões onde observed=true. Sua confiabilidade depende da fonte: uma classificação pgAudit READ é attributed (o banco de dados sabe quem consultou e se foi uma leitura ou escrita); um MCP readOnlyHint é approximate por especificação — a própria especificação MCP diz que anotações de ferramentas não são confiáveis.
Kernel (verdadeiro). O backstop eBPF (signal_source=ebpf) observa no nível de syscall. É o sinal que um agente não pode contornar. Quando a camada eBPF detecta um connect() ou write() que a telemetria cooperativa não reportou, isso não é um gap de registro — é um sinal de anti-evasão. O módulo de segurança une as observações do lado do kernel e do lado cooperativo em uma anomalia correlacionada, de modo que um agente que silencia sua própria telemetria se torna um achado, não um ponto cego.
O mapa de acesso é uma consulta sobre esses vértices, não um esquema separado. A deriva de menor privilégio é o subconjunto onde os dois sinais discordam.
Como a deriva se torna um achado
Um desacordo entre Permitted e Observed é o sinal bruto. O motor o classifica em um dos dois tipos de desvio antes de entrar na fila de anomalias:
// DriftKind classifica um desvio de menor privilégio entre o permitido e o observado.
type DriftKind string
const (
// DriftUnusedGrant é um acesso permitido nunca observado (sobreaprovisionado).
DriftUnusedGrant DriftKind = "unused_grant"
// DriftViolation é um acesso observado que não é permitido.
DriftViolation DriftKind = "violation"
)
unused_grant significa que uma política diz que o agente pode fazer algo que nunca foi visto fazendo. Isto é privilégio morto — risco carregado sem benefício. É o sinal de limpeza para revisões periódicas de acesso: revogar o que não é exercido.
violation significa que o agente foi observado fazendo algo que nenhuma política ou concessão permite. Esta é a constatação ativa. É a linha na tabela de diferenças que lê “escrita não revisada” — a aresta que importa, aquela que a fila de anomalias prioriza.
A classificação não é binária entre “aceitável” e “problema.” A estrutura PrivilegeDrift emparelha a aresta ofensiva com seu tipo:
// PrivilegeDrift é uma discrepância de menor privilégio: uma aresta cujos sinalizadores Permitted
// e Observed não coincidem.
type PrivilegeDrift struct {
Edge AccessEdge
Kind DriftKind
}
A própria borda carrega a proveniência completa: a origem (qual agente), o recurso, o modo de leitura /write, a fonte do sinal que o produziu, a confiança na atribuição e a janela de observação (FirstSeen, LastSeen, OccurrenceCount). Uma detecção de desvio nunca é “algo está errado em algum lugar.” Ela aponta para um agente específico, um recurso específico, um modo de acesso específico, observado por um coletor específico, com um intervalo de tempo.
A fila de anomalias: não apenas “diferente”, mas classificada
Quando o módulo de segurança constrói a visão de anomalias (o endpoint GET /v1/m/security/anomalies), ele puxa os desvios da loja de borda de acesso e classifica cada violation em uma anomalia priorizada. A classificação adiciona contexto que a borda bruta não carrega:
Deriva de acesso. A linha de base: um acesso observado, mas não permitido. A anomalia é intitulada “Acesso inesperado: observado, mas não permitido”, severidade média, e sinalizada com confidence=approximate porque a deriva em nível de loja é o sinal bruto – ainda não reconciliado com o gráfico completo de agente-para-identidade. A visão reconciliada vive no próprio endpoint /drift do mapa de acessos; a fila de anomalias consome o sinal bruto e o rotula de forma honesta.
Suspeita de Egress/exfiltration. Quando o recurso na borda de deriva é um endpoint de rede para um destino externo, não privado (o conector eBPF emite estes como URIs tcp://host:port), a anomalia é reclassificada para egress_exfil_suspected e promovida para severidade alta. Um agente escrevendo em um endpoint externo ao qual nunca recebeu acesso é um tipo de achado diferente de um agente lendo uma tabela de banco de dados para a qual não estava autorizado.
Escalada de sensibilidade. Quando o recurso carrega um rótulo de sensibilidade (high ou secret), a severidade é promovida independentemente de o acesso ser de saída. Um violation contra um recurso de alta sensibilidade justifica triagem mais rápida mesmo que o destino seja interno.
Cada anomalia carrega um mapa evidence com os detalhes brutos:
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,
}
O reconciled: false é deliberado. Ele informa ao consumidor que este é o sinal bruto de nível de loja, não a visão reconciliada do mapa de acesso, do agente para a identidade. A fila de anomalias não espera pela reconciliação para trazer à tona um violation — mas também não finge que a atribuição é firme quando não é.
Níveis de confiança: o que pode ser provado
Cada conexão no mapa de acesso carrega um nível de confiança. O produto utiliza dois:
-
Atribuído (
confidence=attributed): o acesso está firmemente ligado à origem pelas próprias evidências do coletor. Um registro pgAudit nomeando o papel no banco de dados do agente, um evento CloudTrail vinculado às credenciais IAM do agente, uma observação eBPF vinculada a um ID de processo que o tempo de execução resolveu para um agente. A cadeia de atribuição é ponta a ponta. -
Aproximado (
confidence=approximate): a atribuição é inferida e pode ser incompleta. O sinal veio de uma conta de serviço compartilhada onde vários agentes usam a mesma credencial, de um armazenamento com perda (uma instância Redis que não registra a identidade por conexão), ou de uma anotação MCP que a especificação diz não ser confiável. A conexão ainda é um sinal — mas o operador sabe que a prova é mais fraca.
O nível de confiança afeta a pontuação de prioridade da anomalia. A função de prioridade (priorityFor) pontua cada anomalia de 0 a 100, e um desvio de confiança aproximada é descontado:
if confidence == string(sdkmodel.ConfidenceApproximate) {
// desconto: desvio não reconciliado é ruidoso
}
Isso evita que um sinal ruidoso de identidade compartilhada substitua um attributed violation firmemente estabelecido. Ambos aparecem na fila; o approximate fica com classificação menor. É o mesmo princípio aplicado pelo enriquecimento forense: quando uma identidade compartilhada (SharedIdentity: true, AgentCount > 1) é encontrada, a linha do tempo registra que “a atribuição por agente pode ser ambígua” em vez de fingir que a atribuição é exata.
O produto nunca finge certeza. Uma aresta apenas com anotação MCP não tem o mesmo peso que uma corroborada pelo eBPF. Uma descoberta de desvio de uma conta de serviço compartilhada não tem o mesmo peso que uma de uma identidade por agente. O operador vê a diferença e realiza a triagem de acordo.
Desvio na linha do tempo forense
Os achados de deriva não existem apenas na fila de anomalias. Quando um caso forense é aberto e sua linha do tempo é reconstruída a partir do livro de auditoria encadeado por hash, o módulo de segurança enriquece a reconstrução com a deriva do sujeito:
out.Drift = subjectDrift(r.Context(), sc, c.SubjectRef)
A função subjectDrift consulta o armazenamento de borda de acesso por deriva de tipo de violação onde o sujeito é a origem, e retorna uma lista de entradas driftRefDTO — cada uma contendo a origem, recurso, modo de acesso, fonte do sinal, contagem de ocorrências e timestamp da última vez visto. Estas são lidas do próprio cálculo de deriva do armazenamento, não sendo recalculadas pelo módulo de segurança.
A linha do tempo também carrega a atribuição de identidade do sujeito e a linhagem dos dados, então um investigador revisando um caso vê o quadro completo: quem o agente representa (e se essa identidade é compartilhada), o que ele acessou que não deveria, e de quais dados ele derivou respostas. Cada um desses enriquecimentos é tolerante à ausência de vizinhos — se o módulo de conhecimento não estiver instalado, a linhagem é omitida em vez de falsificada; se a identidade não tiver um vínculo de agente resolvido, a atribuição diz “ainda não vinculado” em vez de inventar um.
O ciclo de vida da triagem
Uma descoberta originada de desvio entra no sistema com o status open. A partir daí, ela segue o ciclo de vida padrão de triagem de descobertas:
- aberto: a descoberta existe, ninguém ainda agiu sobre ela.
- triaged: um operador reconheceu, atribuiu para revisão.
- resolved: a causa subjacente foi corrigida (a concessão foi revogada, a política foi reforçada, o agente foi reescopado).
- dismissed: o operador revisou e determinou que não é um risco real (um comportamento conhecido, um falso positivo do approximate).
Toda mudança de estado de triagem é autoauditada para o principal real. O ato de descartar uma constatação é registrado no próprio livro-razão à prova de adulterações, para que um auditor possa ver não apenas qual desvio ocorreu, mas quem revisou e qual foi a decisão. A evidência da constatação (seu tipo, gravidade e hash de detalhes) é imutável após a criação; as mudanças de triagem alteram apenas o estado do fluxo de trabalho.
O que isso significa na prática
Um agente recebe uma chave de API limitada a um workspace Claude. O conector de identidade lê a lista de membros do workspace e emite uma aresta de política: esta chave tem permissão para chamar a API neste workspace. O agente funciona por três semanas. A telemetria mostra que ele está chamando a API nesse workspace — sem desvios. Então, uma mudança de implantação dá ao agente acesso à chave de um segundo workspace. A telemetria observa o agente chamando ambos os workspaces. O segundo workspace não possui uma aresta de política. Uma detecção de desvio do tipo violation é criada: observado, mas não permitido. Ela entra na fila de anomalias como access_drift, gravidade média, confiança approximate (a aresta ainda não foi reconciliada com o grafo de identidade). Se o recurso no segundo workspace tiver um rótulo de sensibilidade high, a gravidade aumenta. A detecção permanece na fila do operador até que alguém a categorize.
Essa é a diferença entre registro e deriva estruturada: o achado é classificado, attributed (com confiança honesta), priorizado e passível de triagem. Ele persiste até que alguém o resolva ou o descarte. Aparece na linha do tempo forense se o agente posteriormente for alvo de um caso de incidente. E cada ação tomada sobre ele é registrada em uma cadeia cuja integridade o produto pode comprovar.
A deriva não é uma métrica a ser minimizada. Ela é um achado a ser triado. O gap entre o que um agente tem permissão para fazer e o que é observado fazendo é a superfície de maior sinal para aplicação do menor privilégio — mas somente quando o gap é estruturado, classificado e honesto sobre o que ele pode comprovar.
Para ver o mapa de acesso e a superfície de deriva em uma propriedade em operação, visite a página do produto do mapa de acesso ou a visão geral do produto.