@a2ui/web_core: `openUrl`関数は、エージェントが提供するボタンアクションを通じて、`javascript:` URIの実行を許可する。
### 概要
`@a2ui/web_core`の`openUrl`関数は、URIスキームの検証を行わずに、エージェントが制御するURLを直接`window.open()`に渡します。悪意のあるエージェントは、`Button`コンポーネントの`functionCall`アクションの`url`引数として`javascript:` URIを提供することができます。ユーザーがレンダリングされたボタンをクリックすると、被害側のアプリケーションのブラウザのオリジンで任意のJavaScriptが実行され、これにより、保存型/反射型XSS攻撃が発生する可能性があります。特別な設定は不要で、デフォルトではBasic Catalogが有効になっています。
### 詳細
この脆弱性は、`@a2ui/web_core`のBasic Catalog内の`openUrl`関数の実装に存在します(コミットID: `23a003248abbf59da6c376ea64ace91d82d209ff`)。
**脆弱性箇所** — `renderers/web_core/src/v0_9/basic_catalog/functions/basic_functions.ts:428-430`:
```ts
export const OpenUrlImplementation = createFunctionImplementation(OpenUrlApi, args => {
if (args.url && typeof window !== 'undefined' && window.open) {
window.open(args.url, '_blank');
}
});
```
`window.open`は、エージェントが提供する`args.url`の値を使用して、条件なしで呼び出されます。スキームの許可リストやブロックリストは適用されていません。
**不十分なスキーマ検証** — `renderers/web_core/src/v0_9/basic_catalog/functions/basic_functions_api.ts:453-458`:
```ts
export const OpenUrlApi = {
name: 'openUrl' as const,
returnType: 'void' as const,
schema: z.object({
url: z.preprocess(v => (v === undefined ? undefined : String(v)), z.string()),
}),
};
```
Zodスキーマは、`string`型のみを要求しており、`javascript:` URIは検証を通過してしまいます。
**完全なデータフロー:**
1. `renderers/web_core/src/v0_9/basic_catalog/components/basic_components.ts:356` — `ButtonApi` は `action: ActionSchema` (エントリーポイント) を受け入れます。
2. `renderers/web_core/src/v0_9/schema/common-types.ts:126-130` — `ActionSchema` は `{ functionCall: FunctionCallSchema }` を許可します。
3. `renderers/web_core/src/v0_9/rendering/generic-binder.ts:243-255` — クリック時に、バインドされたアクションが `resolveDeepSync` を呼び出し、その後 `dispatchAction` を呼び出します。
4. `renderers/web_core/src/v0_9/rendering/data-context.ts:93-105` — `resolveDynamicValue` は `call` キーを検出し、名前付きの関数を呼び出します。
5. `renderers/web_core/src/v0_9/catalog/types.ts:177-186` — カタログ実行関数は `fn.schema.parse(rawArgs)` を実行し、その後 `fn.execute()` を実行します。
6. `renderers/web_core/src/v0_9/basic_catalog/functions/basic_functions_api.ts:453-458` — `OpenUrlApi` は `url` を `z.string()` のみとして検証します (スキームのチェックは行いません)。
7. `renderers/web_core/src/v0_9/basic_catalog/functions/basic_functions.ts:428-430` — **sink**: `window.open(args.url, '_blank')` が `javascript:` URI を実行します。
**A2UI リポジトリで実装されているすべてのレンダラーに影響があります:**
- React: `renderers/react/src/v0_9/catalog/basic/components/Button.tsx:33` — `onClick={props.action}`
- Lit: `renderers/lit/src/v0_9/catalogs/basic/components/Button.ts:112` — `@click=${() => props.action()}`
- Angular: `renderers/angular/src/v0_9/catalog/basic/button.component.ts:103-110` — `handleClick()` → `dataContext.resolveAction` → `dispatchAction`
`web_core` に依存し、その基本的なカタログ実装を使用する、他の A2UI レンダーも影響を受けます。
### 修正
この問題は、[https://github.com/a2ui-project/a2ui/pull/1707](https://github.com/a2ui-project/a2ui/pull/1707) で修正され、web_core のバージョン 0.10.2 でリリースされました。HTTP または HTTPS スキームを使用しない URL、または無効な URL をブロックすることで修正されています。
プロジェクトでこの問題を修正するには、@a2ui/web_core のバージョンが 0.10.2 以上であることを確認してください。
影響を受けるパッケージ:
- npm (JavaScript) @a2ui/web_core: 影響を受けるバージョンは 0.9.0 以降、0.10.2 未満。0.10.2 で修正済み。