a2ui-project / a2ui-project/a2ui

[BUG]: Prototype Pollution in DataModel path resolution

Đang mở
#2,580 1 bình luận 0 reaction 1 người được giao Được @Varun-S10 nhận Xem trên GitHub
P2 status: first-line-handled status: waiting-for-author-response type: bug
Ngôn ngữ chính
TypeScript
Star
16.4k
Fork
1.3k
Merge trung bình
2 ngày 13 giờ
Pull request đã merge (30 ngày)
134

Mô tả

# 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.

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.