FlawOpen

flawopen.com/Teardowns/cve-2026-10032-a2ui-agent-button-xss

● CVE-2026-10032 · CVSS 9.3[1] · Crítica
Investigación · FlawOpen

CVE-2026-10032: XSS en botones A2UI generados por agentes

En las versiones afectadas de @a2ui/web_core, openUrl del Basic Catalog predeterminado enviaba a window.open una URL del agente sin limitar su esquema. Una persona debía pulsar el Button renderizado para producir el impacto sobre el origen del navegador descrito en el aviso; actualiza a 0.10.2 o posterior.[1]

Vector CVSSCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N[1]
💡 Explicación en Lenguaje Sencillo (ELI5)

Imagina un quiosco donde un asistente coloca un botón y escribe el destino en una tarjeta que él mismo proporciona. El quiosco comprueba que haya una dirección, no que lleve a una página web normal. Alguien todavía debe pulsarlo; sin una regla para el destino, el navegador podría interpretar la dirección como instrucciones para el quiosco. La corrección analiza la dirección y solo acepta destinos HTTP o HTTPS.[1], [2]

Conceptos Clave y Términos

A2UI
Protocolo y proyecto de código abierto para interfaces generadas por agentes; el aviso cubre la acción Basic Catalog del paquete web_core.[1]
Catálogo básico
Conjunto integrado de funciones A2UI disponibles para acciones de la interfaz renderizada; el aviso dice que está habilitado por defecto.[1]
Acción de llamada a función
Acción declarativa de UI que nombra una función y aporta argumentos; un Button renderizado podía llamar a openUrl con una URL del agente.[1], [2]
CWE-79
Clasificación de neutralización incorrecta de entradas al generar páginas web; el aviso de A2UI la asigna a este problema de inyección en el navegador.[1], [4]

Mapeos de marcos

  • Referencia CWE para la debilidad descrita en esta guía: CWE-79

Análisis de Causa Raíz

La implementación afectada de Basic Catalog trataba el argumento URL como una cadena para abrir, no como entrada de navegación no confiable que necesita una política de esquemas. La API validaba el tipo cadena, pero el código vulnerable no limitaba el protocolo de la URL analizada antes de llamar a window.open(args.url, '_blank'). Un Button.functionCall controlado por el agente podía llevar el valor al sink. Una persona debía pulsar el botón; el aviso de A2UI describe ejecución de JavaScript en el origen de la aplicación víctima. La corrección upstream analiza el valor con el parser URL, permite solo http: y https: y abre la URL normalizada con noopener,noreferrer. Corrige ese punto de navegación, no garantiza la seguridad de toda UI generada por agentes.[1], [2]

CVE-2026-10032: versiones afectadas y límite de la acción

Condición de despliegueQué confirma el avisoAcción defensiva
@a2ui/web_core 0.9.0, 0.9.1, 0.9.2, 0.10.0 o 0.10.1 con Basic Catalog predeterminado.El aviso enumera estas versiones como afectadas y señala que Basic Catalog viene habilitado por defecto.Actualiza a 0.10.2 o posterior y verifica la versión en la aplicación desplegada.
Una llamada de función Button procede de datos A2UI controlados por agente y alguien hace clic.El aviso describe la ruta hasta openUrl tras el clic y el impacto en el origen del navegador; no es zero-click.Trata los argumentos como no confiables y valídalos en la función que abre la URL.
La aplicación usa los renderizadores React, Lit o Angular de A2UI.El aviso incluye estas integraciones; el límite vulnerable es la acción compartida de Basic Catalog en web_core.Comprueba el paquete y actualiza web_core; no supongas que una configuración del renderer elimina la acción.
La aplicación ejecuta @a2ui/web_core 0.10.2 o posterior.Los mantenedores señalan 0.10.2 como corregido: análisis URL, permiso HTTP/HTTPS y noopener,noreferrer.Mantén pruebas de regresión para esquemas válidos e inválidos y revisa reemplazos propios de openUrl.

Flujo de Ataque Paso a Paso

Paso 1

El agente proporciona una acción para Button

Los datos de UI de A2UI pueden definir un Button con llamada a función y argumentos. Trata como no confiable la acción que proceda de un agente.[1]

Paso 2

Basic Catalog resuelve openUrl

El Basic Catalog predeterminado ofrece openUrl; el esquema exige una cadena, pero el código vulnerable no limitaba el esquema URL.[1]

Paso 3

Una persona pulsa el Button renderizado

El flujo del aviso requiere un clic del usuario. No lo describas como ejecución sin interacción.[1], [2]

Paso 4

La acción llega a window.open

Antes del parche, openUrl pasaba la cadena a window.open sin analizar ni permitir primero el protocolo. El aviso describe ejecución en el origen de la aplicación víctima.[1]

Paso 5

La acción corregida limita la navegación

La corrección resuelve la URL, rechaza protocolos distintos de HTTP y HTTPS y usa noopener,noreferrer. Actualiza a @a2ui/web_core 0.10.2 o posterior.[1], [2]

Código Fuente: Vulnerable vs. Seguro

El fragmento vulnerable procede de la implementación señalada en el aviso A2UI. El corregido representa el cambio upstream de la PR #1707: analizar y resolver la dirección, permitir solo HTTP/HTTPS e impedir que la página abierta controle la página de origen o reciba el referente. Se omiten tipos e imports; no son archivos completos ni una prueba de concepto.[1], [2]

Fragmento de origen: basic_functions.ts — OpenUrlImplementation

IMPLEMENTACIÓN VULNERABLE
export const OpenUrlImplementation = createFunctionImplementation(OpenUrlApi, args => {
  if (args.url && typeof window !== 'undefined' && window.open) {
    window.open(args.url, '_blank');
  }
});
PARCHE SEGURO Y ROBUSTO
export const OpenUrlImplementation = createFunctionImplementation(OpenUrlApi, args => {
  if (args.url && typeof window !== 'undefined' && window.open) {
    const baseHref =
      typeof window.location !== 'undefined' && window.location.href
        ? window.location.href
        : undefined;
    let url: URL;
    try {
      url = baseHref ? new URL(args.url, baseHref) : new URL(args.url);
    } catch (e: any) {
      throw new A2uiExpressionError(`Invalid URL specified: ${args.url}`, 'openUrl', e);
    }

    // Lista estricta de protocolos: solo se permiten HTTP y HTTPS.
    if (url.protocol !== 'https:' && url.protocol !== 'http:') {
      throw new A2uiExpressionError(`Unsupported URL scheme: ${url.protocol}`, 'openUrl');
    }

    // Usa siempre noopener y noreferrer para evitar que la página abierta controle la ventana de origen.
    window.open(url.href, '_blank', 'noopener,noreferrer');
  }
});

Lista de Verificación de Seguridad para Ingeniería

Fuentes