Compare commits

...

6 Commits

Author SHA1 Message Date
pandeymangg
c171850faf fixes lint 2026-03-17 20:07:00 +05:30
Dhruwang
8fdb339b77 fix: use replaceAll instead of replace
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 15:50:55 +05:30
Dhruwang
2a726b432b 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>
2026-03-17 15:42:49 +05:30
Dhruwang
5587057bb3 fix: pre-strip style attributes before DOMPurify to prevent CSP violations
DOMPurify internally uses innerHTML to parse HTML strings. When survey
content (headlines, descriptions) contains style attributes from the
rich text editor, the browser's HTML parser triggers CSP style-src
violations at parse time — before DOMPurify can strip them via
FORBID_ATTR.

Fix: use DOMParser to parse into an inert document (no CSP violations),
remove style attributes from the DOM tree, then pass the clean HTML to
DOMPurify for XSS sanitization.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 15:39:51 +05:30
Dhruwang
f65073bc81 fix: add length guard for regex in stripInlineStyles
Add a 100KB length cap as defense-in-depth against oversized inputs.
The regex itself is O(n) safe — all quantifiers are separated by fixed
literals or use negated character classes — but the cap provides an
extra safety margin.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 15:29:19 +05:30
Dhruwang
5135f2df38 fix: pre-strip style attributes before DOMPurify to prevent CSP violations
DOMPurify internally uses innerHTML to parse HTML strings. When survey
content (headlines, descriptions) contains style attributes from the
rich text editor, the browser's HTML parser triggers CSP `style-src`
violations at parse time — before DOMPurify can strip them via
FORBID_ATTR. Pre-stripping style attributes with a regex ensures the
HTML parser never encounters them.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 15:17:56 +05:30
3 changed files with 18 additions and 13 deletions

View File

@@ -1,5 +1,5 @@
import { type ClassValue, clsx } from "clsx";
import DOMPurify from "isomorphic-dompurify";
import { sanitize } from "isomorphic-dompurify";
import { extendTailwindMerge } from "tailwind-merge";
const twMerge = extendTailwindMerge({
@@ -27,14 +27,16 @@ export function cn(...inputs: ClassValue[]): string {
export const stripInlineStyles = (html: string): string => {
if (!html) return html;
// Use DOMPurify to safely remove style attributes
// This is more secure than regex-based approaches and handles edge cases properly
return DOMPurify.sanitize(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.replaceAll(/ style="[^"]*"| style='[^']*'/gi, "");
return sanitize(preStripped, {
FORBID_ATTR: ["style"],
// Preserve the target attribute (e.g. target="_blank" on links) which is not
// in DOMPurify's default allow-list but is explicitly required downstream.
ADD_ATTR: ["target"],
// Keep other attributes and tags as-is, only remove style attributes
KEEP_CONTENT: true,
});
};

View File

@@ -4,6 +4,7 @@
"baseUrl": ".",
"isolatedModules": true,
"jsx": "react-jsx",
"lib": ["ES2021.String"],
"noEmit": true,
"paths": {
"@/*": ["./src/*"]

View File

@@ -10,14 +10,16 @@ import DOMPurify from "isomorphic-dompurify";
export const stripInlineStyles = (html: string): string => {
if (!html) return html;
// Use DOMPurify to safely remove style attributes
// This is more secure than regex-based approaches and handles edge cases properly
return DOMPurify.sanitize(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.replaceAll(/ style="[^"]*"| style='[^']*'/gi, "");
return DOMPurify.sanitize(preStripped, {
FORBID_ATTR: ["style"],
// Preserve the target attribute (e.g. target="_blank" on links) which is not
// in DOMPurify's default allow-list but is explicitly required downstream.
ADD_ATTR: ["target"],
// Keep other attributes and tags as-is, only remove style attributes
KEEP_CONTENT: true,
});
};