FlawOpen

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

● CVE-2026-10032 · CVSS 9.3[1] · Critique
Recherche · FlawOpen

CVE-2026-10032 : XSS dans les boutons A2UI générés par un agent

Dans les versions touchées de @a2ui/web_core, openUrl du Basic Catalog par défaut transmettait une URL de l’agent à window.open sans limiter son schéma. Une personne devait cliquer sur le Button rendu pour provoquer l’impact sur l’origine du navigateur décrit dans l’avis ; passez à 0.10.2 ou ultérieur.[1]

Vecteur CVSSCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N[1]
💡 Explication en Langage Simple (ELI5)

Imaginez une borne où un assistant place un bouton et inscrit sa destination sur une carte qu’il fournit. La borne vérifie qu’il y a une adresse, pas qu’elle mène à une page Web ordinaire. Un visiteur doit toujours appuyer dessus ; sans règle de destination, le navigateur peut toutefois interpréter l’adresse comme une instruction pour la borne. Le correctif analyse l’adresse et n’accepte que HTTP ou HTTPS.[1], [2]

Concepts Clés et Termes

A2UI
Protocole et projet open source pour les interfaces générées par agents ; l’avis vise l’action Basic Catalog du package web_core.[1]
Catalogue de base
Ensemble intégré de fonctions A2UI pour les actions de l’interface rendue ; l’avis indique qu’il est activé par défaut.[1]
Action d’appel de fonction
Action déclarative qui nomme une fonction et fournit ses arguments ; un Button rendu pouvait appeler openUrl avec une URL de l’agent.[1], [2]
CWE-79
Classification d’une neutralisation incorrecte lors de la génération de pages Web ; l’avis A2UI l’attribue à cette injection côté navigateur.[1], [4]

Correspondances de référentiels

  • Référence CWE pour la faiblesse décrite dans ce guide : CWE-79

Analyse de Cause Racine

L’implémentation Basic Catalog touchée traitait l’argument URL comme une chaîne à ouvrir, et non comme une entrée de navigation non fiable soumise à une politique de schéma. L’API vérifiait le type chaîne, mais le code vulnérable ne limitait pas le protocole avant window.open(args.url, '_blank'). Un Button.functionCall contrôlé par l’agent pouvait transmettre la valeur au sink. Une personne devait cliquer sur le bouton rendu ; l’avis A2UI décrit l’exécution de script dans l’origine de l’application victime. Le correctif amont analyse la valeur, n’autorise que http: et https:, puis ouvre l’URL normalisée avec noopener,noreferrer. Il corrige ce point de navigation sans garantir la sûreté de toute interface générée par agent.[1], [2]

CVE-2026-10032 : versions touchées et limite de l’action

Condition de déploiementÉléments confirmés par l’avisMesure défensive
@a2ui/web_core 0.9.0, 0.9.1, 0.9.2, 0.10.0 ou 0.10.1 avec Basic Catalog par défaut.L’avis répertorie ces versions et indique que Basic Catalog est activé par défaut.Passez à 0.10.2 ou ultérieur et vérifiez la version déployée.
Un appel de fonction Button vient de données A2UI contrôlées par agent et une personne clique.L’avis décrit le clic vers openUrl et l’impact sur l’origine navigateur ; ce n’est pas du zero-click.Traitez les arguments comme non fiables et validez-les dans la fonction qui ouvre l’URL.
L’application utilise un moteur React, Lit ou Angular d’A2UI.L’avis inclut ces intégrations ; la limite vulnérable est l’action Basic Catalog partagée dans web_core.Vérifiez le package et mettez à jour web_core ; un réglage du renderer ne supprime pas forcément l’action.
L’application exécute @a2ui/web_core 0.10.2 ou ultérieur.Les mainteneurs désignent 0.10.2 comme corrigé : analyse URL, autorisation HTTP/HTTPS et noopener,noreferrer.Gardez des tests pour les schémas valides et invalides et examinez tout remplacement personnalisé de openUrl.

Déroulement de l'Attaque Étape par Étape

Étape 1

Un agent fournit une action Button

Les données UI A2UI peuvent définir un Button avec appel de fonction et arguments. Traitez comme non fiable une action venant d’un agent.[1]

Étape 2

Basic Catalog résout openUrl

Le Basic Catalog par défaut expose openUrl ; le schéma exige une chaîne, mais le code vulnérable ne limitait pas le schéma URL.[1]

Étape 3

Une personne clique sur le Button rendu

Le parcours de l’avis exige un clic utilisateur. Ne le présentez pas comme une exécution sans interaction.[1], [2]

Étape 4

L’action atteint window.open

Avant le correctif, openUrl transmettait la chaîne à window.open sans analyser ni autoriser le protocole. L’avis décrit l’exécution dans l’origine de l’application victime.[1]

Étape 5

L’action corrigée limite la navigation

Le correctif résout l’URL, rejette les protocoles autres que HTTP et HTTPS et utilise noopener,noreferrer. Passez à @a2ui/web_core 0.10.2 ou ultérieur.[1], [2]

Code Source : Vulnérable vs Sécurisé

L’extrait vulnérable vient de l’implémentation citée dans l’avis A2UI. L’extrait corrigé représente le changement amont de la PR #1707 : analyser et résoudre l’adresse, n’autoriser que HTTP/HTTPS et empêcher la page ouverte de contrôler la page source ou de recevoir le référent. Types et imports sont omis ; ce ne sont ni des fichiers complets ni une preuve de concept.[1], [2]

Extrait source: basic_functions.ts — OpenUrlImplementation

IMPLÉMENTATION VULNÉRABLE
export const OpenUrlImplementation = createFunctionImplementation(OpenUrlApi, args => {
  if (args.url && typeof window !== 'undefined' && window.open) {
    window.open(args.url, '_blank');
  }
});
PATCH SÉCURISÉ ET ROBUSTE
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);
    }

    // Liste stricte des protocoles : seuls HTTP et HTTPS sont autorisés.
    if (url.protocol !== 'https:' && url.protocol !== 'http:') {
      throw new A2uiExpressionError(`Unsupported URL scheme: ${url.protocol}`, 'openUrl');
    }

    // Utilisez toujours noopener et noreferrer pour empêcher la page ouverte de contrôler la fenêtre d’origine.
    window.open(url.href, '_blank', 'noopener,noreferrer');
  }
});

Liste de Contrôle de Sécurité pour l'Ingénierie

Sources