Skip to content

Commit c7d423b

Browse files
authored
fix: harden SVG sanitization against XSS vectors (JhaSourav07#1899)
## Description Fixes JhaSourav07#1897 Replaces the existing regex-based SVG sanitization in `page.tsx` with a more secure sanitization approach. ### Changes * Removed reliance on regex-only sanitization for SVG content. * Added support for sanitizer-based SVG filtering with an allowlist of safe elements and attributes. * Prevented common SVG XSS vectors, including: * `foreignObject` * `xlink:href` abuse * unsafe `data:` URIs * CSS `url()` injections * inline event handlers * Improved overall SVG rendering security through defense-in-depth practices and safer content handling. ## Pillar * [ ] 🎨 Pillar 1 — New Theme Design * [ ] 📐 Pillar 2 — Geometric SVG Improvement * [ ] 🕐 Pillar 3 — Timezone Logic Optimization * [x] 🛠️ Other (Bug fix, refactoring, docs) ## Checklist before requesting a review: - [x] I have read the `CONTRIBUTING.md` file. - [x] I have tested these changes locally (`localhost:3000/api/streak?user=YOUR_USERNAME`). - [x] I have run `npm run format` and `npm run lint` locally and resolved all errors (CI will fail otherwise). - [x] My commits follow the Conventional Commits format (e.g., `feat(themes): ...`, `fix(calculate): ...`). - [ ] I have updated `README.md` if I added a new theme or URL parameter. - [x] I have started the repo. - [x] I have made sure that i have only one commit to merge in this PR. - [x] The SVG output matches the CommitPulse "premium quality" aesthetic standard (no raw elements, smooth animations, correct fonts). - [ ] (Recommended) I joined the CommitPulse Discord community for contributor discussions, mentorship, and faster PR support.
2 parents bd23853 + fdd9d9f commit c7d423b

1 file changed

Lines changed: 13 additions & 5 deletions

File tree

app/customize/page.tsx

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { motion } from 'framer-motion';
66
import { ControlsPanel } from './components/ControlsPanel';
77
import { ExportPanel } from './components/ExportPanel';
88
import InteractiveViewer from '@/components/InteractiveViewer';
9+
import DOMPurify from 'dompurify';
910
import type {
1011
ExportFormat,
1112
Font,
@@ -142,11 +143,18 @@ export default function CustomizePage(): ReactElement {
142143
})
143144
.then((text) => {
144145
if (!text) return;
145-
// Basic SVG sanitization to prevent XSS (strip scripts and inline event handlers)
146-
const sanitized = text
147-
.replace(/<script[\s\S]*?>[\s\S]*?<\/script>/gi, '')
148-
.replace(/on\w+\s*=\s*("[^"]*"|'[^']*')/gi, '');
149-
setSvgContent(sanitized);
146+
// Sanitize SVG using DOMPurify with the SVG profile.
147+
// - Forbid risky tags like foreignObject and embedded content
148+
// - Forbid xlink:href to avoid external references
149+
// - Use a conservative URI whitelist to prevent javascript: URIs
150+
const sanitized = DOMPurify.sanitize(text, {
151+
USE_PROFILES: { svg: true },
152+
FORBID_TAGS: ['foreignObject', 'iframe', 'object', 'embed', 'script'],
153+
FORBID_ATTR: ['xlink:href'],
154+
ALLOWED_URI_REGEXP: /^(?:(?:https?|mailto|data):|#)/i,
155+
});
156+
157+
setSvgContent(sanitized as string);
150158
setSvgState('loaded');
151159
setErrorMessage(null);
152160
})

0 commit comments

Comments
 (0)