Signed Agent Cards: prevención de envenenamiento y suplantación con JWS

11 min de lectura
1name · description · versionerror2supportedInterfaces[] · url · protocolBinding · protocolVersionerror3capabilities · defaultInputModes · defaultOutputModeserror4skills[] · id · name · description · tagserror5securitySchemes · securitywarning6provider · signatures[]warning
La verificación criptográfica se sitúa en la capa de confianza del flujo de validación de Agent Card, garantizando la integridad de los metadatos antes de iniciar cualquier ejecución remota de agentes.

Cuando los agentes de IA se descubren entre sí en redes públicas recuperando un archivo agent.json, la confianza no puede depender ciegamente de la red. Una tarjeta sin firmar está a solo un secuestro de DNS o un error de CDN de redirigir sistemas autónomos a endpoints maliciosos. En A2A v1.0, las Signed Agent Cards resuelven este problema mediante JSON Web Signatures (JWS).

Por qué las tarjetas no firmadas son vulnerables

En la Especificación del protocolo A2A, el descubrimiento está diseñado para ser ligero, estático y sin autenticación: un agente cliente realiza una simple petición HTTP GET a /.well-known/agent.json.

Si bien esta simplicidad aceleró la adopción del ecosistema, introduce una superficie de ataque crítica conocida en seguridad empresarial como Agent Card Poisoning (envenenamiento de Agent Card):

  1. Redirección de endpoints: Un atacante que comprometa una entrada DNS o un proxy perimetral puede reescribir el campo supportedInterfaces[].url, enviando silenciosamente prompts sensibles a un servidor de escucha o suplantación.
  2. Inyección de capacidades y prompts: Al manipular el array skills o las descripciones, los actores maliciosos pueden engañar a los agentes llamantes para que deleguen tareas financieras o administrativas críticas a un modelo no verificado.
  3. Suplantación de identidad: Sin verificación criptográfica, cualquiera puede alojar una tarjeta de agente afirmando en provider.organization que representa a una institución financiera de confianza o un proveedor de software reconocido.

Para defender las arquitecturas multiagente frente a estos riesgos, la especificación oficial mantenida por el repositorio a2aproject/A2A formaliza el array signatures basándose en el estándar RFC 7515: JSON Web Signature (JWS).

Anatomía del array signatures

En una Agent Card de A2A v1.0, la propiedad de nivel superior signatures contiene un array de objetos de firma. Esto permite que una tarjeta sea firmada por múltiples autoridades; por ejemplo, el proveedor que desarrolló el agente y un auditor de cumplimiento de seguridad externo.

Cada entrada adopta el formato estándar de serialización JWS Flattened JSON o el formato JWS compacto canónico:

Fragmento de Agent Card con firmas JWS
{
  "name": "Treasury Reconciliation Agent",
  "version": "1.2.0",
  "supportedInterfaces": [
    {
      "url": "https://agents.acme-finance.com/a2a/v1",
      "protocolBinding": "JSONRPC",
      "protocolVersion": "1.0"
    }
  ],
  "signatures": [
    {
      "protected": "eyJhbGciOiJFUzI1NiIsImtpZCI6IjIwMjYtMDktY29yZSIsInR5cCI6IkpXUyJ9",
      "signature": "MEQCIFz8fV9Q2b6HqVqYx3...7k1vU8X3g"
    }
  ]
}

Los campos dentro de cada objeto de firma funcionan de la siguiente manera:

  • protected: Cadena JSON codificada en Base64URL que contiene los parámetros del encabezado JWS:
    • alg: El algoritmo criptográfico utilizado (como ES256 o RS256).
    • kid: Identificador de clave, que resuelve a la clave pública de verificación alojada en el almacén de confianza del proveedor.
    • crit: (Opcional) Array de extensiones de encabezado críticas que el agente verificador debe reconocer obligatoriamente.
  • signature: Firma digital codificada en Base64URL calculada sobre la carga útil normalizada y el encabezado protegido.

Firma de un agent.json con ES256

Para firmar una Agent Card, la carga útil del documento debe canonicizarse de forma determinista (eliminando cualquier campo signatures existente antes de firmar) a fin de garantizar una generación consistente del hash en diferentes lenguajes y entornos de ejecución.

A continuación se muestra una implementación de referencia en Node.js utilizando la API estándar Web Crypto:

sign-agent-card.mjs
import crypto from 'node:crypto';
import fs from 'node:fs';

// 1. Leer tarjeta y eliminar firmas existentes para payload canónico
const rawCard = JSON.parse(fs.readFileSync('agent.json', 'utf8'));
const { signatures, ...unsignedPayload } = rawCard;
const payloadString = JSON.stringify(unsignedPayload);

// 2. Preparar JWS Protected Header
const header = {
  alg: 'ES256',
  kid: 'https://acme-finance.com/.well-known/jwks.json#key-2026',
  typ: 'JWS'
};

const base64Url = (str) => Buffer.from(str).toString('base64url');

const protectedHeaderB64 = base64Url(JSON.stringify(header));
const payloadB64 = base64Url(payloadString);
const signingInput = `${protectedHeaderB64}.${payloadB64}`;

// 3. Firmar usando clave privada EC (P-256)
const privateKeyPem = fs.readFileSync('private-key.pem', 'utf8');
const signer = crypto.createSign('SHA256');
signer.update(signingInput);
signer.end();

const signatureB64 = signer.sign(privateKeyPem, 'base64url');

// 4. Adjuntar bloque de firmas a la Agent Card
const signedCard = {
  ...rawCard,
  signatures: [
    {
      protected: protectedHeaderB64,
      signature: signatureB64
    }
  ]
};

fs.writeFileSync('agent.signed.json', JSON.stringify(signedCard, null, 2));
console.log('✓ Agent Card firmada con éxito usando ES256');

Cómo los agentes clientes verifican las firmas

Cuando un agente cliente recupera una Agent Card de un homólogo no verificado previamente, la verificación debe ocurrir antes de inspeccionar capacidades o invocar interfaces:

  1. Extracción: Analizar la clave signatures del documento. Si no existe, marcarla como no verificada o rechazarla según las políticas de seguridad internas.
  2. Decodificación de encabezado: Decodificar protected mediante base64url e inspeccionar alg y kid. Rechazar algoritmos que no cumplan con la línea base de seguridad (por ejemplo, descartar algoritmos inseguros como none o longitudes de clave obsoletas).
  3. Obtención de claves: Obtener la clave pública referenciada por kid. Verificar que el dominio de la URL de la clave coincida rigurosamente con el provider.url declarado en la tarjeta.
  4. Validación de firma: Reconstruir la carga útil no firmada, calcular el resumen canónico y verificar la firma criptográfica contra la clave pública.

Rotación de claves y lista de verificación de seguridad

Siga estas recomendaciones operativas al gestionar Signed Agent Cards en producción:

  • Desacople el ciclo de vida de claves del despliegue: Utilice identificadores de clave (kid) que apunten a una URL JWKS (/.well-known/jwks.json) en lugar de codificar claves estáticas directamente. Esto permite una rotación de claves transparente y sin interrupciones.
  • Exija HTTPS en todos los endpoints: Cada interfaz listada en supportedInterfaces y cada endpoint de claves debe requerir HTTPS con certificados TLS válidos.
  • Vincule el dominio al proveedor: Asegúrese de que el dominio que aloja la Agent Card coincida exactamente con el provider.url y el origen del endpoint JWKS.
  • Auditoría previa al despliegue: Compruebe siempre su tarjeta terminada en el validador antes de publicarla en la raíz pública de su dominio.

Preguntas frecuentes

¿Son obligatorias las firmas JWS en una Agent Card bajo A2A v1.0?

Son opcionales en el esquema base, pero muy recomendadas para cualquier agente en producción expuesto a redes públicas o entornos multinquilino. Sin firmas, los agentes clientes no pueden certificar si la tarjeta fue alterada en tránsito.

¿Qué es el "envenenamiento de Agent Card" (Agent Card Poisoning)?

Ocurre cuando un atacante altera un documento agent.json (por ejemplo, mediante envenenamiento de caché DNS, errores de configuración en CDN o ataques man-in-the-middle) para redirigir endpoints hacia infraestructuras maliciosas o inyectar descripciones de habilidades falsificadas.

¿Qué algoritmo criptográfico se recomienda para Signed Agent Cards?

Se recomienda ES256 (ECDSA utilizando P-256 y SHA-256) por el tamaño compacto de su firma y su alto rendimiento. RS256 (RSA con SHA-256) también está ampliamente soportado para compatibilidad con infraestructuras PKI empresariales heredadas.

¿Dónde deben alojarse las claves públicas o los endpoints JWKS?

Las claves públicas deben publicarse bajo HTTPS en el dominio autoritativo del proveedor, comúnmente en /.well-known/jwks.json, o referenciarse mediante los parámetros kid o x5u en el encabezado protegido JWS.

¿Cómo evalúa las firmas el validador de Agent Card?

El validador comprueba que el array signatures contenga objetos JWS compactos o aplanados bien estructurados, con encabezados protegidos válidos, identificadores de algoritmos estándar y referencias a claves verificables.

Referencias

  1. Especificación del protocolo A2A (a2a-protocol.org)a2a-protocol.org
  2. Repositorio del protocolo A2A (a2aproject/A2A)github.com/a2aproject/A2A
  3. RFC 7515: JSON Web Signature (JWS)datatracker.ietf.org/doc/html/rfc7515

Herramienta relacionada: Validador de Agent Card

Siguiente paso

Compruebe la integridad de su Agent Card antes de desplegarla.

El validador inspecciona la estructura de su tarjeta, comprueba el formato de firma JWS y advierte sobre referencias a claves públicas faltantes o endpoints no cifrados.