From 09da6a1d7b2c5f705cfa526f6ee13f0136983fae Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 10 Feb 2026 03:35:57 +0000 Subject: [PATCH] feat(security): enhance DOM sanitization to strip dangerous URIs Updated `sanitizeElement` to strictly remove whitespace and control characters from URI attributes before validation. This prevents bypasses like `java\tscript:` in `href`, `src`, `action`, and `formaction` attributes. Added comprehensive unit tests covering these bypass vectors. Co-authored-by: AEmotionStudio <163354043+AEmotionStudio@users.noreply.github.com> --- src/shared/utils.ts | 4 +++- tests/unit/Security.test.ts | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/shared/utils.ts b/src/shared/utils.ts index 4135fdf..15eb4a2 100644 --- a/src/shared/utils.ts +++ b/src/shared/utils.ts @@ -210,7 +210,9 @@ export function sanitizeElement(element: HTMLElement): void { // 2. Remove javascript: URIs in specific attributes if (['href', 'src', 'action', 'formaction'].includes(attrName)) { - if (attrValue.startsWith('javascript:')) { + // Strip all whitespace and control characters to prevent bypasses like "java\tscript:" + const normalizedValue = attrValue.replace(/[\s\x00-\x1F\x7F]/g, ''); + if (normalizedValue.startsWith('javascript:')) { element.removeAttribute(attributes[i].name); } } diff --git a/tests/unit/Security.test.ts b/tests/unit/Security.test.ts index 9242deb..c2b5ef5 100644 --- a/tests/unit/Security.test.ts +++ b/tests/unit/Security.test.ts @@ -60,6 +60,25 @@ describe('Security', () => { expect(form.hasAttribute('formaction')).toBe(false); }); + it('should remove obscured javascript: URIs (whitespace bypass)', () => { + const window = new Window(); + const document = window.document; + const link = document.createElement('a'); + + // Bypass attempts: tabs, newlines, spaces + link.setAttribute('href', 'java\tscript:alert(1)'); + sanitizeElement(link as unknown as HTMLElement); + expect(link.hasAttribute('href')).toBe(false); + + link.setAttribute('href', 'java\nscript:alert(1)'); + sanitizeElement(link as unknown as HTMLElement); + expect(link.hasAttribute('href')).toBe(false); + + link.setAttribute('href', ' javascript:alert(1)'); + sanitizeElement(link as unknown as HTMLElement); + expect(link.hasAttribute('href')).toBe(false); + }); + it('should preserve safe URLs', () => { const window = new Window(); const document = window.document;