mirror of
https://github.com/formbricks/formbricks.git
synced 2026-03-17 23:56:49 -05:00
fix: pre-strip style attributes before DOMPurify to prevent CSP violations
DOMPurify internally uses innerHTML to parse HTML strings. When survey content contains style attributes, the browser triggers CSP style-src violations at parse time — before FORBID_ATTR can strip them. Fix: use a simple regex with negated character classes bounded by fixed quote delimiters (O(n), no backtracking) to strip style attributes from the raw string before passing to DOMPurify. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -27,19 +27,14 @@ export function cn(...inputs: ClassValue[]): string {
|
||||
export const stripInlineStyles = (html: string): string => {
|
||||
if (!html) return html;
|
||||
|
||||
let cleanHtml = html;
|
||||
// Pre-strip style attributes from the raw string BEFORE DOMPurify parses it.
|
||||
// DOMPurify internally uses innerHTML to parse HTML, which triggers CSP
|
||||
// `style-src` violations at parse time — before FORBID_ATTR can strip them.
|
||||
// The regex is O(n) safe: [^"]* and [^']* are negated classes bounded by
|
||||
// fixed quote delimiters, so no backtracking can occur.
|
||||
const preStripped = html.replace(/ style="[^"]*"| style='[^']*'/gi, "");
|
||||
|
||||
// In browser environments, pre-strip style attributes using DOMParser.
|
||||
// DOMParser creates an inert document that does NOT trigger CSP violations,
|
||||
// unlike DOMPurify's internal innerHTML which fires style-src violations
|
||||
// at parse time — before FORBID_ATTR can strip them.
|
||||
if (typeof DOMParser !== "undefined") {
|
||||
const doc = new DOMParser().parseFromString(html, "text/html");
|
||||
doc.querySelectorAll("[style]").forEach((el) => el.removeAttribute("style"));
|
||||
cleanHtml = doc.body.innerHTML;
|
||||
}
|
||||
|
||||
return DOMPurify.sanitize(cleanHtml, {
|
||||
return DOMPurify.sanitize(preStripped, {
|
||||
FORBID_ATTR: ["style"],
|
||||
ADD_ATTR: ["target"],
|
||||
KEEP_CONTENT: true,
|
||||
|
||||
@@ -10,19 +10,14 @@ import DOMPurify from "isomorphic-dompurify";
|
||||
export const stripInlineStyles = (html: string): string => {
|
||||
if (!html) return html;
|
||||
|
||||
let cleanHtml = html;
|
||||
// Pre-strip style attributes from the raw string BEFORE DOMPurify parses it.
|
||||
// DOMPurify internally uses innerHTML to parse HTML, which triggers CSP
|
||||
// `style-src` violations at parse time — before FORBID_ATTR can strip them.
|
||||
// The regex is O(n) safe: [^"]* and [^']* are negated classes bounded by
|
||||
// fixed quote delimiters, so no backtracking can occur.
|
||||
const preStripped = html.replace(/ style="[^"]*"| style='[^']*'/gi, "");
|
||||
|
||||
// In browser environments, pre-strip style attributes using DOMParser.
|
||||
// DOMParser creates an inert document that does NOT trigger CSP violations,
|
||||
// unlike DOMPurify's internal innerHTML which fires style-src violations
|
||||
// at parse time — before FORBID_ATTR can strip them.
|
||||
if (typeof DOMParser !== "undefined") {
|
||||
const doc = new DOMParser().parseFromString(html, "text/html");
|
||||
doc.querySelectorAll("[style]").forEach((el) => el.removeAttribute("style"));
|
||||
cleanHtml = doc.body.innerHTML;
|
||||
}
|
||||
|
||||
return DOMPurify.sanitize(cleanHtml, {
|
||||
return DOMPurify.sanitize(preStripped, {
|
||||
FORBID_ATTR: ["style"],
|
||||
ADD_ATTR: ["target"],
|
||||
KEEP_CONTENT: true,
|
||||
|
||||
Reference in New Issue
Block a user