From ccb54dac9d4baa59996bc1bb33bf9968f14761cb Mon Sep 17 00:00:00 2001 From: Braintree Date: Mon, 8 Jul 2024 23:33:26 +0000 Subject: [PATCH] feat: re-handle embedded encoding, add tests Co-authored-by: Iris Booker --- src/__tests__/index.test.ts | 17 +++++++++++++++++ src/index.ts | 16 +++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/__tests__/index.test.ts b/src/__tests__/index.test.ts index bcbd71a..180d891 100644 --- a/src/__tests__/index.test.ts +++ b/src/__tests__/index.test.ts @@ -146,6 +146,23 @@ describe("sanitizeUrl", () => { expect(sanitizeUrl(vector)).toBe(BLANK_URL); }); }); + + it("backslash prefixed attack vectors", () => { + const attackVectors = [ + "\fjavascript:alert()", + "\vjavascript:alert()", + "\tjavascript:alert()", + "\njavascript:alert()", + "\rjavascript:alert()", + "\u0000javascript:alert()", + "\u0001javascript:alert()", + "\j\av\a\s\cript:alert()", + ]; + + attackVectors.forEach((vector) => { + expect(sanitizeUrl(vector)).toBe(BLANK_URL); + }); + }); describe("invalid protocols", () => { describe.each(["javascript", "data", "vbscript"])("%s", (protocol) => { diff --git a/src/index.ts b/src/index.ts index 350510b..9c1d71d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -29,6 +29,17 @@ function isValidUrl(url: string): boolean { } } +function decodeURI(uri: string): string { + try { + return decodeURIComponent(uri); + } catch (e: unknown) { + // Ignoring error + // It is possible that the URI contains a `%` not associated + // with URI/URL-encoding. + return uri; + } +} + function sanitizeString(str: string): string { return str .replace(/[^a-zA-Z0-9-_./]/g, '') @@ -43,7 +54,7 @@ export function sanitizeUrl(url?: string): string { } let charsToDecode; - let decodedUrl = url.trim(); + let decodedUrl = decodeURI(url.trim()); do { decodedUrl = decodeHtmlCharacters(decodedUrl) @@ -51,6 +62,9 @@ export function sanitizeUrl(url?: string): string { .replace(ctrlCharactersRegex, "") .replace(whitespaceEscapeCharsRegex, "") .trim(); + + decodedUrl = decodeURI(decodedUrl); + charsToDecode = decodedUrl.match(ctrlCharactersRegex) || decodedUrl.match(htmlEntitiesRegex) ||