Saltar al contenido

least-privilege

Permitido vs observado: la deriva como hallazgo de primera clase

Por Olivares AI 11 min de lectura

Un post complementario introdujo la deriva de mínimo privilegio como la brecha entre lo que un agente de IA tiene permitido hacer y lo que se observa que hace. Aquel post cubrió el concepto: por qué se forma la brecha, cómo la observación read-first produce un diff permitido-vs-observado, y cómo la política como código lo cierra en tiempo de acceso. Este post baja una capa más — a cómo la deriva se convierte en un hallazgo estructurado, clasificado y triageable dentro del módulo de seguridad, y qué sucede con él una vez que existe.

La versión corta: la deriva no es una métrica de dashboard ni una línea de log. Es una entidad persistida con una clasificación, una severidad, un nivel de confianza y un ciclo de vida de triaje. Alimenta la cola de anomalías, enriquece timelines forenses y es honesta sobre lo que puede y no puede demostrar.

Las tres fuentes de señal

Cada edge en el mapa de acceso registra una relación de acceso entre un origen (un agente, una identidad, una sesión) y un recurso. Cada edge lleva dos flags booleanos: Permitted y Observed. Los edges interesantes son aquellos donde esos flags discrepan.

Pero los flags no aparecen de la nada. Provienen de fuentes de señal distintas, cada una con un perfil de confianza diferente:

Policy (permitido). Un edge con signal_source=policy o signal_source=scoped_grant representa una concesión declarada: algo que una credencial, un rol IAM o el propio plano de source-scoping de la plataforma dice que este agente tiene permitido hacer. Estos edges son permitted=true, observed=false hasta que la telemetría los corrobora. Son el techo. Los conectores de identidad (issuers WIF, rosters de API keys, roles de workspace) alimentan este lado. Una cuenta de servicio federada con permiso para el scope OAuth de su regla en un workspace es uno de estos edges.

Telemetría (observado). Señales cooperativas de trazas de OpenTelemetry, logs de pgAudit, registros de CloudTrail, anotaciones MCP, observaciones del protocolo A2A y webhooks de GitHub/GitLab. Producen edges donde observed=true. Su confianza depende de la fuente: una clasificación READ de pgAudit es attributed (la base de datos sabe quién consultó y si fue una lectura o una escritura); un readOnlyHint de MCP es approximate por especificación — la propia especificación MCP dice que las anotaciones de herramienta no son de confianza.

Kernel (verdad de base). El backstop eBPF (signal_source=ebpf) observa a nivel de syscall. Es la señal que un agente no puede eludir. Cuando la capa eBPF ve un connect() o un write() que la telemetría cooperativa no reportó, no es una laguna de logging — es una señal de anti-evasión. El módulo de seguridad une las observaciones del lado kernel y del lado cooperativo en una anomalía correlada, de modo que un agente que silencia su propia telemetría se convierte en un hallazgo, no en un punto ciego.

El mapa de acceso es una consulta sobre estos edges, no un esquema aparte. La deriva de mínimo privilegio es el subconjunto donde los dos flags discrepan.

Cómo la deriva se convierte en hallazgo

Una discrepancia entre Permitted y Observed es la señal bruta. El engine la clasifica en una de dos clases de deriva antes de que entre en la cola de anomalías:

// DriftKind classifies a least-privilege drift between permitted and observed.
type DriftKind string

const (
    // DriftUnusedGrant is a permitted access never observed (over-provisioned).
    DriftUnusedGrant DriftKind = "unused_grant"
    // DriftViolation is an observed access that is not permitted.
    DriftViolation DriftKind = "violation"
)

unused_grant significa que una política dice que el agente puede hacer algo que nunca se le ha visto hacer. Es privilegio muerto — riesgo que cargas sin beneficio. Es la señal de limpieza para las revisiones periódicas de acceso: revoca lo que no se ejerce.

violation significa que se observó al agente haciendo algo que ninguna política o concesión permite. Este es el hallazgo activo. Es la fila de la tabla diff que dice “escritura no revisada” — el edge que importa, el que la cola de anomalías prioriza.

La clasificación no es binaria entre “bien” y “problema.” La struct PrivilegeDrift empareja el edge infractor con su clase:

// PrivilegeDrift is one least-privilege discrepancy: an edge whose Permitted
// and Observed flags disagree.
type PrivilegeDrift struct {
    Edge AccessEdge
    Kind DriftKind
}

El propio edge lleva toda la procedencia: el origen (qué agente), el recurso, el modo de lectura/escritura, la fuente de señal que lo produjo, la confianza en la atribución y la ventana de observación (FirstSeen, LastSeen, OccurrenceCount). Un hallazgo de deriva nunca es “algo va mal en algún sitio.” Apunta a un agente concreto, un recurso concreto, un modo de acceso concreto, observado por un colector concreto, con un rango temporal.

La cola de anomalías: no solo “diferente,” sino clasificado

Cuando el módulo de seguridad construye la vista de anomalías (el endpoint GET /v1/m/security/anomalies), extrae la deriva del almacén de access-edges y clasifica cada violation en una anomalía priorizada. La clasificación añade contexto que el edge bruto no lleva:

Access drift. La línea base: un acceso observado pero no permitido. La anomalía se titula “Unexpected access: observed but not permitted,” severidad media, y se marca con confidence=approximate porque la deriva a nivel de store es la señal bruta — aún no reconciliada contra el grafo completo de agente-a-identidad. La vista reconciliada vive en el propio endpoint /drift del mapa de acceso; la cola de anomalías consume la señal bruta y la etiqueta honestamente.

Egress/exfiltración sospechada. Cuando el recurso en el edge de deriva es un endpoint de red hacia un destino externo, no privado (el conector eBPF los emite como URIs tcp://host:port), la anomalía se reclasifica a egress_exfil_suspected y se promueve a severidad alta. Un agente escribiendo a un endpoint externo al que nunca se le concedió acceso es una forma de hallazgo diferente a un agente leyendo una tabla de base de datos para la que no tenía scope.

Escalado por sensibilidad. Cuando el recurso lleva una etiqueta de sensibilidad (high o secret), la severidad se promueve independientemente de si el acceso es egress. Una violation contra un recurso de alta sensibilidad justifica un triaje más rápido aunque el destino sea interno.

Cada anomalía lleva un mapa de evidence con los detalles crudos:

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,
}

El reconciled: false es deliberado. Dice al consumidor que esta es la señal bruta a nivel de store, no la vista reconciliada agente-a-identidad del mapa de acceso. La cola de anomalías no espera a la reconciliación para sacar a la superficie una violation — pero no pretende que la atribución es firme cuando no lo es.

Niveles de confianza: qué se puede demostrar

Cada edge en el mapa de acceso lleva un nivel de confianza. El producto usa dos:

  • Attributed (confidence=attributed): el acceso está firmemente vinculado al origen por la propia evidencia del colector. Un registro pgAudit que nombra el rol de base de datos del agente, un evento CloudTrail vinculado a las credenciales IAM del agente, una observación eBPF vinculada a un ID de proceso que el runtime resolvió a un agente. La cadena de atribución es extremo a extremo.

  • Approximate (confidence=approximate): la atribución está inferida y puede tener pérdida de información. La señal vino de una cuenta de servicio compartida donde múltiples agentes usan la misma credencial, de un almacén con pérdidas (una instancia de Redis que no registra identidad por conexión), o de una anotación MCP que la especificación dice que no es de confianza. El edge sigue siendo una señal — pero el operador sabe que la prueba es más débil.

El nivel de confianza afecta a la puntuación de prioridad de la anomalía. La función de prioridad (priorityFor) puntúa cada anomalía de 0 a 100, y una deriva con confianza approximate se descuenta:

if confidence == string(sdkmodel.ConfidenceApproximate) {
    // discount: unreconciled drift is noisy
}

Esto evita que una señal ruidosa de identidad compartida desplace una violation firmemente atribuida. Ambas aparecen en la cola; la approximate se posiciona más abajo. Es el mismo principio que aplica el enriquecimiento forense: cuando se encuentra una identidad compartida (SharedIdentity: true, AgentCount > 1), el timeline anota que “per-agent attribution may be ambiguous” en lugar de pretender que la atribución es exacta.

El producto nunca finge certeza. Un edge basado solo en anotaciones MCP no lleva el mismo peso que uno corroborado por eBPF. Un hallazgo de deriva de una cuenta de servicio compartida no lleva el mismo peso que uno de una identidad per-agent. El operador ve la diferencia y triaja en consecuencia.

La deriva en el timeline forense

Los hallazgos de deriva no existen solo en la cola de anomalías. Cuando se abre un caso forense y su timeline se reconstruye a partir del ledger de auditoría con cadena de hashes, el módulo de seguridad enriquece la reconstrucción con la deriva del sujeto:

out.Drift = subjectDrift(r.Context(), sc, c.SubjectRef)

La función subjectDrift consulta el almacén de access-edges buscando deriva de tipo violation donde el sujeto es el origen, y devuelve una lista de entradas driftRefDTO — cada una con el origen, recurso, modo de acceso, fuente de señal, conteo de ocurrencias y timestamp de última observación. Se leen del propio cómputo de drift del store, no se recalculan en el módulo de seguridad.

El timeline también lleva la atribución de identidad del sujeto y su linaje de datos, de modo que un investigador revisando un caso ve el cuadro completo: como quién actúa el agente (y si esa identidad es compartida), a qué accedió que no debería, y de qué datos derivó respuestas. Cada uno de esos enriquecimientos tolera la ausencia del módulo vecino — si el módulo de knowledge no está instalado, el linaje se omite en lugar de fabricarse; si la identidad no tiene un binding de agente resuelto, la atribución dice “not yet bound” en lugar de inventar uno.

El ciclo de vida de triaje

Un hallazgo originado por deriva entra en el sistema con estado open. A partir de ahí sigue el ciclo de vida estándar de triaje de hallazgos:

  • open: el hallazgo existe, nadie ha actuado sobre él todavía.
  • triaged: un operador lo reconoció, lo asignó para revisión.
  • resolved: la causa subyacente se corrigió (la concesión se revocó, la política se ajustó, el agente se reacotó).
  • dismissed: el operador lo revisó y determinó que no es un riesgo real (un comportamiento conocido, un falso positivo por atribución approximate).

Cada cambio de estado de triaje se auto-audita al principal real. El acto de descartar un hallazgo se registra él mismo en el ledger tamper-evident, de modo que un auditor puede ver no solo qué deriva ocurrió sino quién la revisó y qué decidió. La evidencia del hallazgo (su kind, severidad y hash de detalle) es inmutable tras la creación; el triaje cambia solo el estado del flujo de trabajo.

Qué significa esto en la práctica

A un agente se le da una API key con scope para un workspace de Claude. El conector de identidad lee el roster del workspace y emite un edge de policy: esta key tiene permitido llamar a la API en este workspace. El agente funciona durante tres semanas. La telemetría muestra que llama a la API en ese workspace — sin deriva. Entonces un cambio de despliegue le da al agente acceso a la key de un segundo workspace. La telemetría observa al agente llamando a ambos workspaces. El segundo workspace no tiene edge de policy. Se crea un hallazgo de deriva de tipo violation: observado pero no permitido. Entra en la cola de anomalías como access_drift, severidad media, confianza approximate (el edge aún no se ha reconciliado contra el grafo de identidad). Si el recurso en el segundo workspace lleva una etiqueta de sensibilidad high, la severidad se promueve. El hallazgo permanece en la cola del operador hasta que alguien lo triaje.

Esa es la diferencia entre logging y deriva estructurada: el hallazgo está clasificado, atribuido (con confianza honesta), priorizado y es triageable. Persiste hasta que alguien lo resuelve o lo descarta. Aparece en el timeline forense si el agente es luego sujeto de un caso de incidente. Y cada acción tomada sobre él se registra en una cadena cuya integridad el producto puede demostrar.


La deriva no es una métrica a minimizar. Es un hallazgo a triajear. La brecha entre lo que un agente tiene permitido hacer y lo que se observa que hace es la superficie de mayor señal para la aplicación de mínimo privilegio — pero solo cuando la brecha está estructurada, clasificada y es honesta sobre lo que puede demostrar.

Para ver el mapa de acceso y la superficie de deriva sobre un entorno en funcionamiento, visita la página de producto del mapa de acceso o la vista general de producto.

Artículos relacionados

Preguntas frecuentes

¿Cuál es la diferencia entre una deriva unused_grant y una violation?

Un unused_grant es un acceso permitido que nunca se observó -- privilegio muerto que el agente mantiene pero no ejerce. Una violation es lo inverso: un acceso observado que ninguna política o concesión permite. Ambos son deriva, pero conllevan perfiles de riesgo distintos y expectativas de respuesta diferentes. Un unused_grant es un objetivo de limpieza; una violation es un hallazgo activo que puede requerir triaje inmediato.

¿Por qué la cola de anomalías descuenta la deriva con confianza approximate?

Cuando un edge de deriva se marca como approximate, su atribución está inferida, no demostrada. Puede originarse en una cuenta de servicio compartida donde la atribución por agente colapsa, o en una fuente de señal con pérdida de información. Descontarlo en la puntuación de prioridad evita que deriva no reconciliada y potencialmente ruidosa desplace hallazgos de mayor confianza. La deriva sigue apareciendo en la cola; simplemente se posiciona más abajo hasta que la atribución se confirme o un operador la triaje.

Mira a qué pueden llegar tus agentes

Olivares AI es la plataforma abierta y self-hosted para tu parque de IA. Despliégalo en tu propia infraestructura y obtén el mapa de acceso que tus equipos de seguridad y plataforma llevan pidiendo.