facebook / lexical

Lexical is an extensible text editor framework that provides excellent reliability, accessibility and performance.
https://lexical.dev
MIT License
19.95k stars 1.7k forks source link

[lexical] Bug Fix: DOM Clobbering Gadget found in rollup bundled scripts that leads to XSS #6756

Closed lamcodeofpwnosec closed 4 weeks ago

lamcodeofpwnosec commented 1 month ago

We discovered a DOM Clobbering vulnerability in rollup when bundling scripts that use import.meta.url or with plugins that emit and reference asset files from code in cjs/umd/iife format. The DOM Clobbering gadget can lead to cross-site scripting (XSS) in web pages where scriptless attacker-controlled HTML elements (e.g., an img tag with an unsanitized name attribute) are present.

Backgrounds DOM Clobbering is a type of code-reuse attack where the attacker first embeds a piece of non-script, seemingly benign HTML markups in the webpage (e.g. through a post or comment) and leverages the gadgets (pieces of js code) living in the existing javascript code to transform it into executable code. More for information about DOM Clobbering, here are some references:

Gadget found in rollup We have identified a DOM Clobbering vulnerability in rollup bundled scripts, particularly when the scripts uses import.meta and set output in format of cjs/umd/iife. In such cases, rollup replaces meta property with the URL retrieved from document.currentScript.

PoC

Considering a website that contains the following main.js script, the devloper decides to use the rollup to bundle up the program: rollup main.js --format cjs --file bundle.js.

var s = document.createElement('script')
s.src = import.meta.url + 'extra.js'
document.head.append(s)

The output bundle.js is shown in the following code snippet.

'use strict';

var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
var s = document.createElement('script');
s.src = (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && False && _documentCurrentScript.src || new URL('bundle.js', document.baseURI).href)) + 'extra.js';
document.head.append(s);

Patch Patching the following two functions with type checking would be effective mitigations against DOM Clobbering attack.

const getRelativeUrlFromDocument = (relativePath: string, umd = false) =>
    getResolveUrl(
        `'${escapeId(relativePath)}', ${
            umd ? `typeof document === 'undefined' ? location.href : ` : ''
        }document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT' && document.currentScript.src || document.baseURI`
    );
const getUrlFromDocument = (chunkId: string, umd = false) =>
    `${
        umd ? `typeof document === 'undefined' ? location.href : ` : ''
    }(${DOCUMENT_CURRENT_SCRIPT} && ${DOCUMENT_CURRENT_SCRIPT}.tagName.toUpperCase() === 'SCRIPT' &&${DOCUMENT_CURRENT_SCRIPT}.src || new URL('${escapeId(
        chunkId
    )}', document.baseURI).href)`;

Impact

This vulnerability can result in cross-site scripting (XSS) attacks on websites that include rollup-bundled files (configured with an output format of cjs, iife, or umd and use import.meta) and allow users to inject certain scriptless HTML tags without properly sanitizing the name or id attributes.

CVE-2024-47068 CWE-79

vercel[bot] commented 1 month ago

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
lexical ✅ Ready (Inspect) Visit Preview 💬 Add feedback Oct 23, 2024 8:47am
lexical-playground ✅ Ready (Inspect) Visit Preview 💬 Add feedback Oct 23, 2024 8:47am
github-actions[bot] commented 1 month ago

size-limit report 📦

Path Size
lexical - cjs 29.94 KB (0%)
lexical - esm 29.78 KB (0%)
@lexical/rich-text - cjs 38.6 KB (0%)
@lexical/rich-text - esm 31.64 KB (0%)
@lexical/plain-text - cjs 37.2 KB (0%)
@lexical/plain-text - esm 29 KB (0%)
@lexical/react - cjs 40.34 KB (0%)
@lexical/react - esm 33 KB (0%)