FlawOpen

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

● CVE-2026-10032 · CVSS 9.3[1] · Critical
FlawOpen Security Research

CVE-2026-10032: A2UI Agent-Generated Button XSS

In affected @a2ui/web_core releases, the default Basic Catalog's openUrl action passed an agent-supplied URL to window.open without restricting its scheme. A person had to click the rendered Button for the advisory's browser-origin impact; upgrade to 0.10.2 or later.[1]

CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N[1]
💡 Plain English Explainer (ELI5)

Imagine a kiosk where an assistant can place a button, but the button's destination is written on a card the assistant supplies. The kiosk checks that the card contains an address, not that it leads to an ordinary web page. A visitor still has to press the button, but without a destination rule the browser may treat the address as instructions for the kiosk itself. The fix makes the kiosk parse the address and accept only HTTP or HTTPS destinations.[1], [2]

Core Concepts & Subsystem Terms

A2UI
An open-source protocol and renderer project for agent-generated user interfaces; the advisory covers the web_core package's Basic Catalog action.[1]
Basic Catalog
A2UI's built-in set of functions available to rendered UI actions. The advisory says it is enabled by default.[1]
Function call action
A declarative UI action that names a function and supplies arguments; here, a rendered Button could invoke openUrl with an agent-supplied URL.[1], [2]
CWE-79
Improper neutralization of input during web-page generation, the weakness classification assigned by the A2UI advisory to this browser-side injection issue.[1], [4]

Framework mappings

  • CWE reference for the weakness described in this guide: CWE-79

Root Cause Analysis

The affected Basic Catalog implementation treated the URL argument as a string to open, not as untrusted navigation input that needed a scheme policy. The action API validated the argument's string type but the vulnerable implementation did not restrict the parsed URL protocol before calling window.open(args.url, '_blank'). An agent-controlled Button.functionCall could therefore carry the value to this sink. A person still had to click the rendered button; the A2UI advisory describes script execution in the victim application's browser origin. The upstream fix resolves the value with the URL parser, permits only http: and https:, then opens the normalized URL with noopener,noreferrer. This is a specific fix for this navigation sink, not a general guarantee that agent-generated UI is safe.[1], [2]

CVE-2026-10032: affected versions and action boundary

Deployment conditionWhat the advisory establishesDefensive action
@a2ui/web_core 0.9.0, 0.9.1, 0.9.2, 0.10.0, or 0.10.1 with the default Basic Catalog.The A2UI advisory lists these releases as affected and says the Basic Catalog is enabled by default.Upgrade to 0.10.2 or later and verify the resolved version in the deployed application.
A Button function call is supplied through agent-controlled A2UI data and a person clicks it.The advisory describes the click-triggered openUrl path and its browser-origin impact. It does not make the issue a zero-click vulnerability.Treat action arguments as untrusted and validate them at the function implementation that opens the URL.
An application uses A2UI's React, Lit, or Angular renderer integration.The A2UI advisory includes these renderer integrations in the affected scope; the vulnerable boundary is the shared web_core Basic Catalog action.Check package resolution and update the shared web_core dependency rather than assuming a renderer-specific setting removes the action.
The application runs @a2ui/web_core 0.10.2 or later.The maintainers identify 0.10.2 as the fixed release; its patch parses URLs, permits HTTP/HTTPS, and uses noopener,noreferrer.Retain regression tests for valid and invalid schemes and review any custom replacement for openUrl.

Step-by-Step Attack Flow

Step 1

Agent-authored UI includes a navigation action

The agent supplies A2UI data that defines a Button and its openUrl function call.[1]

Step 2

A person activates the Button

The documented path depends on a user click; the advisory does not describe a zero-click trigger.[1]

Step 3

The unvalidated URL reaches the browser navigation API

The vulnerable openUrl implementation passed its string argument directly to window.open without a protocol allowlist.[1], [2]

Step 4

The browser-origin boundary is crossed

The A2UI advisory describes arbitrary script execution in the victim app's origin. This impact statement is attributed to the advisory; no real-world incident is asserted here.[1]

Step 5

Upgrade and enforce the fixed URL policy

Version 0.10.2 adds URL parsing, an HTTP/HTTPS-only protocol check, and noopener,noreferrer when opening a new tab.[1], [2]

Source Code: Flaw vs. Secure Implementation

The vulnerable excerpt is from the A2UI implementation identified by the maintainer advisory. The hardened excerpt represents the merged upstream change in PR #1707: parse and resolve the address, allow only HTTP/HTTPS protocols, and prevent the opened page from controlling its opener or receiving a referrer. The surrounding project types and imports are omitted, so these focused excerpts are not standalone files or a proof of concept.[1], [2]

Source excerpt: basic_functions.ts — OpenUrlImplementation

UNPATCHED FLAW
export const OpenUrlImplementation = createFunctionImplementation(OpenUrlApi, args => {
  if (args.url && typeof window !== 'undefined' && window.open) {
    window.open(args.url, '_blank');
  }
});
HARDENED SECURE PATCH
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);
    }

    // Strict protocol allowlist: Only HTTP and HTTPS are permitted.
    if (url.protocol !== 'https:' && url.protocol !== 'http:') {
      throw new A2uiExpressionError(`Unsupported URL scheme: ${url.protocol}`, 'openUrl');
    }

    // Always use noopener and noreferrer to prevent reverse tab-nabbing
    window.open(url.href, '_blank', 'noopener,noreferrer');
  }
});

Engineering & System Hardening Checklist

Sources