32f40921567a21c3c174d3f0a3adc2d6a4d2e5b1
<style> was previously in FORBID_TAGS and stripped entirely. It's now allowed, but its CSS is rewritten by a new hand-rolled scoper (src/utils/scope-css.ts) so a customer's rules only match inside their own block's wrapper -- never leak out and restyle the rest of the page. The wrapper div (class="whp-html-<hash>") is only emitted when a block actually has surviving <style> content, so blocks that don't use it stay byte-identical to before this change. Key findings, both covered by tests: - DOMPurify's body-only serialization silently drops a <style> tag that appears before any other content in a block (the HTML5 parser implicitly places it in <head>, which DOMPurify never looks at). Fixed with FORCE_BODY: true. - DOMPurify does not sanitize CSS declaration values at all (expression(), behavior:, url() to any host all pass through verbatim) -- @import is stripped explicitly by scopeCss() since it's the one CSS-level exfiltration/fetch vector in scope here. Scope identifier reuses the existing djb2 stableHash() from utils/escape.ts (already used for this exact class of problem) over the block's own `code` string -- deterministic, no node id, no Math.random/Date.now. 1141/1141 tests passing (was 1077), tsc clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Description
Visual drag-and-drop website builder using GrapesJS
3.5 MiB
Languages
TypeScript
64.8%
HTML
16.1%
JavaScript
14.9%
CSS
3.2%
PHP
0.7%
Other
0.3%