a2ui-project / a2ui-project/a2ui

[BUG]: Prototype Pollution in DataModel path resolution

オープン
#2,580 コメント 1 件 リアクション 0 件 担当者 1 名 @Varun-S10 が担当を希望しています GitHub で見る
P2 status: first-line-handled status: waiting-for-author-response type: bug
主要言語
TypeScript
スター
16.4k
フォーク
1.3k
平均マージ
2日 13時間
マージ済み PR(30日)
134

説明

# Location
renderers/lit_internal/src/v0_8/data/model-processor.ts:251

# Description
The DataModel.set method in renderers/web_core/src/v0_8/data/model-processor.ts processes arbitrary user-supplied path strings (from an A2UI message payload) to recursively traverse or create properties on nested objects/maps. Specifically, const segments = this.normalizePath(path).split('/').filter(s => s); extracts the keys, and in the loop, if the target key is missing, it dynamically populates the object. Crucially, there is no validation step to block keys like __proto__, constructor, or prototype before they are assigned. Given that current can eventually resolve to a native Object (via this.objCtor or isObject(value) branches or when custom map structures fall back to objects depending on user inputs or framework quirks), this lack of filtering makes it possible to write to __proto__ and therefore overwrite properties on Object.prototype.

# Impact
Prototype Pollution allowing global state manipulation in the host web application, which can often be escalated to XSS (Cross-Site Scripting) or other critical client-side vulnerabilities.

# Mitigation
Implement a check during path segment traversal to block or ignore keys known to cause prototype pollution, specifically __proto__, constructor, and prototype. For example, throw an error or skip the segment if ['__proto__', 'constructor', 'prototype'].includes(segment).

# Reproduction Steps
Construct an A2UI message of type dataModelUpdate targeting an existing surface.
Set the path to /__proto__/polluted. Alternatively, provide a contents array with a key like __proto__ and a nested valueMap that sets polluted.
Send the message to the renderer.
Observe if Object.prototype.polluted is now set in the browser console.

# Evidence
```
let current: DataMap | DataArray = root;
for (let i = 0; i < segments.length - 1; i++) {
const segment = segments[i];
let target: DataValue | undefined;

if (current instanceof this.mapCtor) {
target = current.get(segment);
} else if (Array.isArray(current) && /^\\d+$/.test(segment)) {
target = current[parseInt(segment, 10)];
}

if (
target === undefined ||
typeof target !== \"object\" ||
target === null
) {
target = new this.mapCtor();
if (current instanceof this.mapCtor) {
current.set(segment, target);
} else if (Array.isArray(current)) {
current[parseInt(segment, 10)] = target;
}
}
current = target as DataMap | DataArray;
}
```

# Reasoning
The setDataByPath method in renderers/lit_internal/src/v0_8/data/model-processor.ts and renderers/web_core/src/v0_8/data/model-processor.ts processes arbitrary user-supplied path strings (from an A2UI message payload) to recursively traverse or create properties on nested objects/maps. Specifically, const segments = this.normalizePath(path).split('/').filter(s => s); extracts the keys, and in the loop, if the target key is missing, it dynamically populates the object. Crucially, there is no validation step to block keys like __proto__, constructor, or prototype before they are assigned. Given that current can eventually resolve to a native Object (via this.objCtor or isObject(value) branches or when custom map structures fall back to objects depending on user inputs or framework quirks), this lack of filtering makes it possible to write to __proto__ and therefore overwrite properties on Object.prototype.

コントリビューションガイド

コントリビューションガイドを開く

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。