ASI03
OWASP Agentic Top 10 DATOS

Abuso de identidad y privilegios

Descripción

Los agentes heredan credenciales excesivas de sus operadores, almacenan en caché tokens de autenticación en memoria accesible, o escalan privilegios a través de los límites entre agentes para acceder a recursos fuera de su alcance autorizado.

Riesgo

Panorama del riesgo

Los agentes normalmente se ejecutan con las credenciales del usuario o de la cuenta de servicio que los inició. Esto crea un problema de amplificación de privilegios: un usuario humano que puede acceder a 10 sistemas ahora tiene un agente que puede acceder a esos mismos 10 sistemas a velocidad de máquina, 24/7, sin la fricción cognitiva que normalmente limita el mal uso humano. Peor aún, los agentes pueden almacenar tokens en caché, compartir credenciales entre sesiones, o descubrir que pueden autenticarse ante servicios a los que su operador no pretendía que llegaran.

Superficie de ataque

  • Cuentas de servicio con privilegios excesivos: los agentes se ejecutan bajo cuentas de servicio amplias con acceso que excede considerablemente los requisitos de su tarea
  • Almacenamiento en caché y filtración de tokens: tokens OAuth, claves de API o cookies de sesión almacenados en la memoria del agente, el historial de conversación o archivos de registro, desde donde pueden extraerse
  • Escalamiento de privilegios entre agentes: el Agente A delega una tarea al Agente B, pasando las credenciales del Agente A, lo que otorga al Agente B un acceso que no debería tener
  • Persistencia de credenciales: tokens que sobreviven a la sesión del agente, permaneciendo en memoria o en archivos temporales después de que la tarea finaliza
  • Autoridad implícita del entorno (ambient authority): agentes que heredan todos los permisos de su entorno de alojamiento (roles de IAM en la nube, cuentas de servicio de Kubernetes) sin delimitación de alcance

Impacto en el negocio

  • Acceso no autorizado a datos: el agente accede a bases de datos, recursos compartidos de archivos o API más allá del alcance de su tarea, utilizando credenciales heredadas amplias
  • Cadenas de escalamiento de privilegios: un agente comprometido de bajo privilegio aprovecha tokens almacenados en caché para alcanzar objetivos de alto valor
  • Vacíos en el rastro de auditoría: las acciones realizadas bajo cuentas de servicio compartidas no pueden atribuirse a agentes o tareas específicas
  • Violaciones de cumplimiento: infringe los requisitos del principio de mínimo privilegio de SOC 2, ISO 27001 y otros marcos regulatorios

Escenarios de ataque

Un agente de revisión de código se ejecuta bajo una cuenta de servicio de CI/CD que tiene acceso de lectura/escritura a todos los repositorios, la gestión de secretos y los pipelines de despliegue. Un atacante desencadena una revisión sobre un PR malicioso que contiene inyección de prompts. El agente secuestrado utiliza sus amplias credenciales para leer secretos del vault, clonar repositorios privados y hacer push de un commit con puerta trasera a la rama principal de un servicio crítico no relacionado.

Un agente almacena en caché un token bearer de OAuth en su memoria de conversación después de autenticarse ante una API interna. Una sesión de usuario posterior en la misma instancia del agente extrae el token almacenado en caché desde la ventana de contexto del agente y lo utiliza para acceder a los recursos del usuario anterior — una filtración de credenciales entre inquilinos (cross-tenant).

El Agente A (soporte al cliente, bajo privilegio) delega una búsqueda de datos al Agente B (analítica, alto privilegio). El Agente A pasa el contexto de su tarea, incluyendo una cadena de conexión a base de datos almacenada en caché. El Agente B almacena este contexto para referencia futura. Más tarde, el Agente B utiliza las credenciales de base de datos del Agente A en combinación con sus propios permisos de analítica para acceder a datos de clientes a los que ningún agente debería llegar de forma independiente.

Mitigaciones

Credenciales justo a tiempo

Nunca precargar a los agentes con credenciales de larga duración:

  • Emitir tokens de corta duración y con alcance limitado en el momento de cada invocación de herramienta
  • Los tokens deben expirar en cuestión de minutos, no horas — idealmente vinculados a una sola llamada de API
  • Utilizar un broker de credenciales que emita tokens bajo demanda según la tarea y la identidad actuales del agente
  • Revocar los tokens inmediatamente al finalizar la tarea o al terminar el agente

Autorización por acción

Autorizar cada acción de forma individual en lugar de otorgar acceso general:

  • Implementar un punto de decisión de políticas (PDP) que evalúe cada llamada a herramienta contra el contexto de autorización actual del agente
  • Las decisiones de autorización deben considerar: identidad del agente, tarea actual, recurso de destino, tipo de acción y hora del día
  • Denegar por defecto — los agentes no tienen acceso hasta que se les otorgue explícitamente para una operación específica
  • Registrar todas las decisiones de autorización para su auditoría

Delimitación del alcance de credenciales

Limitar el alcance de las credenciales al mínimo requerido:

  • Utilizar credenciales específicas por recurso (un token por API, no un token para todas las API)
  • Implementar restricciones de audiencia en los tokens para que no puedan usarse contra servicios no previstos
  • Aplicar vinculación por IP o por certificado de cliente para evitar la reutilización (replay) de tokens desde hosts no autorizados
  • Nunca incluir credenciales en las ventanas de contexto del agente, el historial de conversación o la salida de registros

Aislamiento de identidad del agente

Evitar compartir credenciales a través de los límites entre agentes:

  • Cada instancia de agente debe tener una identidad única e intransferible
  • La delegación entre agentes debe usar las credenciales propias del agente delegado, no las del agente delegante
  • Implementar autenticación entre agentes para que los agentes receptores puedan verificar la identidad del delegante sin recibir sus credenciales
  • Eliminar todo el material de credenciales de la memoria cuando finalicen las sesiones del agente

Atribución de auditoría

Asegurar que cada acción sea atribuible a un agente y una tarea específicos:

  • Etiquetar todas las llamadas a la API con el ID del agente, el ID de la tarea y un ID de correlación
  • Utilizar cuentas de servicio separadas por rol de agente, nunca cuentas compartidas
  • Implementar no repudio mediante registros de acciones firmados

Ejemplos de código

Proveedor de Credenciales Acotadas

import time
import uuid
import hashlib
import secrets
from dataclasses import dataclass
from typing import Optional


@dataclass
class TokenAcotado:
    token: str
    id_agente: str
    id_tarea: str
    recurso: str
    acciones: list[str]
    expira_en: float
    huella_digital: str

    @property
    def esta_expirado(self) -> bool:
        return time.time() > self.expira_en


class ProveedorCredenciales:
    """Emite credenciales acotadas y de corta duración para las invocaciones de herramientas del agente."""

    def __init__(self, ttl_segundos: int = 120):
        self._ttl = ttl_segundos
        self._tokens_activos: dict[str, TokenAcotado] = {}
        self._revocados: set[str] = set()

    def emitir_token(
        self,
        id_agente: str,
        id_tarea: str,
        recurso: str,
        acciones: list[str],
    ) -> TokenAcotado:
        """Genera un token de corta duración acotado a un recurso y un conjunto de acciones."""
        valor_token = secrets.token_urlsafe(32)
        huella_digital = hashlib.sha256(
            f"{id_agente}:{id_tarea}:{recurso}:{time.time()}".encode()
        ).hexdigest()[:16]

        token = TokenAcotado(
            token=valor_token,
            id_agente=id_agente,
            id_tarea=id_tarea,
            recurso=recurso,
            acciones=acciones,
            expira_en=time.time() + self._ttl,
            huella_digital=huella_digital,
        )
        self._tokens_activos[valor_token] = token
        return token

    def validar_token(
        self, valor_token: str, recurso: str, accion: str
    ) -> dict:
        """Valida que el token esté activo, no haya expirado y esté acotado para la solicitud."""
        if valor_token in self._revocados:
            return {"valido": False, "razon": "El token ha sido revocado"}

        token = self._tokens_activos.get(valor_token)
        if not token:
            return {"valido": False, "razon": "Token no encontrado"}

        if token.esta_expirado:
            self._limpiar_token(valor_token)
            return {"valido": False, "razon": "Token expirado"}

        if token.recurso != recurso:
            return {"valido": False, "razon": f"Token no acotado para el recurso '{recurso}'"}

        if accion not in token.acciones:
            return {"valido": False, "razon": f"Acción '{accion}' no permitida por el token"}

        return {"valido": True, "id_agente": token.id_agente, "id_tarea": token.id_tarea}

    def revocar_todos_para_tarea(self, id_tarea: str) -> int:
        """Revoca todos los tokens asociados a una tarea finalizada."""
        contador_revocados = 0
        for valor_token, token in list(self._tokens_activos.items()):
            if token.id_tarea == id_tarea:
                self._revocados.add(valor_token)
                del self._tokens_activos[valor_token]
                contador_revocados += 1
        return contador_revocados

    def _limpiar_token(self, valor_token: str):
        self._tokens_activos.pop(valor_token, None)

Requisitos de evidencia

  • Registros de emisión y validación de tokens con atribución de agente/tarea
  • Auditoría del alcance de credenciales que muestra tokens correspondientes al mínimo privilegio requerido
  • Registros de delegación entre agentes que demuestran el aislamiento de credenciales
  • Informes del ciclo de vida de los tokens que muestran el cumplimiento del TTL y la integridad de las revocaciones
  • Revisión periódica de accesos que confirma la ausencia de cuentas de servicio obsoletas o con privilegios excesivos