From c826564c9e50e58c77229f3febc1b5f36f53828a Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sun, 8 Mar 2026 23:25:47 +0200 Subject: [PATCH] chore(spreadsheet): address requested changes --- .../lib/spreadsheet/render_to_html.spec.ts | 113 ++++++++++++++++++ .../src/lib/spreadsheet/render_to_html.ts | 47 ++++++-- 2 files changed, 152 insertions(+), 8 deletions(-) diff --git a/packages/commons/src/lib/spreadsheet/render_to_html.spec.ts b/packages/commons/src/lib/spreadsheet/render_to_html.spec.ts index ab83c25898..dd3f10e26a 100644 --- a/packages/commons/src/lib/spreadsheet/render_to_html.spec.ts +++ b/packages/commons/src/lib/spreadsheet/render_to_html.spec.ts @@ -305,4 +305,117 @@ describe("renderSpreadsheetToHtml", () => { expect(html).toContain("text-align:center"); expect(html).toContain("border-bottom:"); }); + + it("sanitizes CSS injection in color values", () => { + const input = JSON.stringify({ + version: 1, + workbook: { + sheetOrder: ["s1"], + styles: {}, + sheets: { + s1: { + id: "s1", + name: "Sheet1", + hidden: 0, + rowCount: 10, + columnCount: 5, + mergeData: [], + cellData: { + "0": { + "0": { + v: "test", + s: { + bg: { rgb: "red;background:url(//evil.com/steal)" }, + cl: { rgb: "#FFF;color:expression(alert(1))" } + } + } + } + }, + rowData: {}, + columnData: {} + } + } + } + }); + + const html = renderSpreadsheetToHtml(input); + expect(html).not.toContain("evil.com"); + expect(html).not.toContain("expression"); + expect(html).toContain("transparent"); + }); + + it("sanitizes CSS injection in font-family", () => { + const input = JSON.stringify({ + version: 1, + workbook: { + sheetOrder: ["s1"], + styles: {}, + sheets: { + s1: { + id: "s1", + name: "Sheet1", + hidden: 0, + rowCount: 10, + columnCount: 5, + mergeData: [], + cellData: { + "0": { + "0": { + v: "test", + s: { + ff: "Arial;}" + } + } + } + }, + rowData: {}, + columnData: {} + } + } + } + }); + + const html = renderSpreadsheetToHtml(input); + expect(html).not.toContain("