feat(html_sanitizer): enforce strict style rules (closes #931)

This commit is contained in:
Elian Doran 2025-02-22 09:18:47 +02:00
parent 1d47df5f28
commit ef4fc0a180
No known key found for this signature in database
2 changed files with 74 additions and 0 deletions

View File

@ -0,0 +1,53 @@
import { describe, expect, it } from "vitest";
import html_sanitizer from "./html_sanitizer.js";
import { trimIndentation } from "../../spec/support/utils.js";
describe("sanitize", () => {
it("filters out position inline CSS", () => {
const dirty = `<div style="z-index:999999999;margin:0px;left:250px;height:100px;display:table;background:none;position:fixed;top:250px;"></div>`;
const clean = `<div></div>`;
expect(html_sanitizer.sanitize(dirty)).toBe(clean);
});
it("keeps inline styles defined in CKEDitor", () => {
const dirty = trimIndentation`\
<p>
<span style="color:hsl(0, 0%, 90%);">
Hi
</span>
<span style="background-color:hsl(30, 75%, 60%);">
there
</span>
</p>
<figure class="table" style="float:left;height:800px;width:600px;">
<table style="background-color:hsl(0, 0%, 90%);border-color:hsl(0, 0%, 0%);border-style:dotted;">
<tbody>
<tr>
<td style="border:2px groove hsl(60, 75%, 60%);"></td>
</tr>
</tbody>
</table>
</figure>`;
const clean = trimIndentation`\
<p>
<span style="color:hsl(0, 0%, 90%)">
Hi
</span>
<span style="background-color:hsl(30, 75%, 60%)">
there
</span>
</p>
<figure class="table" style="float:left;height:800px;width:600px">
<table style="background-color:hsl(0, 0%, 90%);border-color:hsl(0, 0%, 0%);border-style:dotted">
<tbody>
<tr>
<td style="border:2px groove hsl(60, 75%, 60%)"></td>
</tr>
</tbody>
</table>
</figure>`;
expect(html_sanitizer.sanitize(dirty)) .toBe(clean);
});
});

View File

@ -141,6 +141,9 @@ function sanitize(dirtyHtml: string) {
allowedTags = DEFAULT_ALLOWED_TAGS;
}
const colorRegex = [/^#(0x)?[0-9a-f]+$/i, /^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/, /^hsl\(\s*(\d{1,3})\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*\)$/];
const sizeRegex = [/^\d+(?:px|em|%)$/];
// to minimize document changes, compress H
return sanitizeHtml(dirtyHtml, {
allowedTags,
@ -148,6 +151,24 @@ function sanitize(dirtyHtml: string) {
"*": ["class", "style", "title", "src", "href", "hash", "disabled", "align", "alt", "center", "data-*"],
input: ["type", "checked"]
},
allowedStyles: {
"*": {
"color": colorRegex,
"background-color": colorRegex
},
"figure": {
"float": [ /^\s*(left|right|none)\s*$/ ],
"width": sizeRegex,
"height": sizeRegex
},
"table": {
"border-color": colorRegex,
"border-style": [ /^\s*(none|hidden|dotted|dashed|solid|double|groove|ridge|inset|outset)\s*$/ ]
},
"td": {
"border": [ /^\s*\d+(?:px|em|%)\s*(none|hidden|dotted|dashed|solid|double|groove|ridge|inset|outset)\s*(#(0x)?[0-9a-fA-F]+|rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)|hsl\(\s*(\d{1,3})\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\))\s*$/ ]
}
},
allowedSchemes: ALLOWED_PROTOCOLS,
nonTextTags: ["head"],
transformTags