@braintree/sanitize-url
Advanced tools
+4
-0
| # CHANGELOG | ||
| ## 7.0.2 | ||
| - Improve sanitization of whitespace escapes | ||
| ## 7.0.1 | ||
@@ -4,0 +8,0 @@ |
@@ -6,3 +6,4 @@ export declare const invalidProtocolRegex: RegExp; | ||
| export declare const urlSchemeRegex: RegExp; | ||
| export declare const whitespaceEscapeCharsRegex: RegExp; | ||
| export declare const relativeFirstCharacters: string[]; | ||
| export declare const BLANK_URL = "about:blank"; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| exports.BLANK_URL = exports.relativeFirstCharacters = exports.urlSchemeRegex = exports.ctrlCharactersRegex = exports.htmlCtrlEntityRegex = exports.htmlEntitiesRegex = exports.invalidProtocolRegex = void 0; | ||
| exports.BLANK_URL = exports.relativeFirstCharacters = exports.whitespaceEscapeCharsRegex = exports.urlSchemeRegex = exports.ctrlCharactersRegex = exports.htmlCtrlEntityRegex = exports.htmlEntitiesRegex = exports.invalidProtocolRegex = void 0; | ||
| exports.invalidProtocolRegex = /^([^\w]*)(javascript|data|vbscript)/im; | ||
@@ -9,3 +9,4 @@ exports.htmlEntitiesRegex = /&#(\w+)(^\w|;)?/g; | ||
| exports.urlSchemeRegex = /^.+(:|:)/gim; | ||
| exports.whitespaceEscapeCharsRegex = /(\\|%5[cC])((%(6[eE]|72|74))|[nrt])/g; | ||
| exports.relativeFirstCharacters = [".", "/"]; | ||
| exports.BLANK_URL = "about:blank"; |
+16
-2
@@ -15,2 +15,13 @@ "use strict"; | ||
| } | ||
| function decodeURI(uri) { | ||
| try { | ||
| return decodeURIComponent(uri); | ||
| } | ||
| catch (e) { | ||
| // Ignoring error | ||
| // It is possible that the URI contains a `%` not associated | ||
| // with URI/URL-encoding. | ||
| return uri; | ||
| } | ||
| } | ||
| function sanitizeUrl(url) { | ||
@@ -21,3 +32,3 @@ if (!url) { | ||
| var charsToDecode; | ||
| var decodedUrl = url; | ||
| var decodedUrl = decodeURI(url); | ||
| do { | ||
@@ -27,7 +38,10 @@ decodedUrl = decodeHtmlCharacters(decodedUrl) | ||
| .replace(constants_1.ctrlCharactersRegex, "") | ||
| .replace(constants_1.whitespaceEscapeCharsRegex, "") | ||
| .trim(); | ||
| decodedUrl = decodeURI(decodedUrl); | ||
| charsToDecode = | ||
| decodedUrl.match(constants_1.ctrlCharactersRegex) || | ||
| decodedUrl.match(constants_1.htmlEntitiesRegex) || | ||
| decodedUrl.match(constants_1.htmlCtrlEntityRegex); | ||
| decodedUrl.match(constants_1.htmlCtrlEntityRegex) || | ||
| decodedUrl.match(constants_1.whitespaceEscapeCharsRegex); | ||
| } while (charsToDecode && charsToDecode.length > 0); | ||
@@ -34,0 +48,0 @@ var sanitizedUrl = decodedUrl; |
+1
-1
| { | ||
| "name": "@braintree/sanitize-url", | ||
| "version": "7.0.1", | ||
| "version": "7.0.2", | ||
| "description": "A url sanitizer", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -130,2 +130,22 @@ /* eslint-disable no-script-url */ | ||
| it("removes whitespace escape sequences", () => { | ||
| const attackVectors = [ | ||
| "javascri\npt:alert('xss')", | ||
| "javascri\rpt:alert('xss')", | ||
| "javascri\tpt:alert('xss')", | ||
| "javascrip\\%74t:alert('XSS')", | ||
| "javascrip%5c%72t:alert()", | ||
| "javascrip%5Ctt:alert()", | ||
| "javascrip%255Ctt:alert()", | ||
| "javascrip%25%35Ctt:alert()", | ||
| "javascrip%25%35%43tt:alert()", | ||
| "javascrip%25%32%35%25%33%35%25%34%33rt:alert()", | ||
| "javascrip%255Crt:alert('%25xss')", | ||
| ]; | ||
| attackVectors.forEach((vector) => { | ||
| expect(sanitizeUrl(vector)).toBe(BLANK_URL); | ||
| }); | ||
| }); | ||
| describe("invalid protocols", () => { | ||
@@ -132,0 +152,0 @@ describe.each(["javascript", "data", "vbscript"])("%s", (protocol) => { |
+2
-0
@@ -7,3 +7,5 @@ export const invalidProtocolRegex = /^([^\w]*)(javascript|data|vbscript)/im; | ||
| export const urlSchemeRegex = /^.+(:|:)/gim; | ||
| export const whitespaceEscapeCharsRegex = | ||
| /(\\|%5[cC])((%(6[eE]|72|74))|[nrt])/g; | ||
| export const relativeFirstCharacters = [".", "/"]; | ||
| export const BLANK_URL = "about:blank"; |
+20
-2
@@ -9,2 +9,3 @@ import { | ||
| urlSchemeRegex, | ||
| whitespaceEscapeCharsRegex, | ||
| } from "./constants"; | ||
@@ -24,2 +25,13 @@ | ||
| 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; | ||
| } | ||
| } | ||
| export function sanitizeUrl(url?: string): string { | ||
@@ -30,3 +42,4 @@ if (!url) { | ||
| let charsToDecode; | ||
| let decodedUrl = url; | ||
| let decodedUrl = decodeURI(url); | ||
| do { | ||
@@ -36,7 +49,12 @@ decodedUrl = decodeHtmlCharacters(decodedUrl) | ||
| .replace(ctrlCharactersRegex, "") | ||
| .replace(whitespaceEscapeCharsRegex, "") | ||
| .trim(); | ||
| decodedUrl = decodeURI(decodedUrl); | ||
| charsToDecode = | ||
| decodedUrl.match(ctrlCharactersRegex) || | ||
| decodedUrl.match(htmlEntitiesRegex) || | ||
| decodedUrl.match(htmlCtrlEntityRegex); | ||
| decodedUrl.match(htmlCtrlEntityRegex) || | ||
| decodedUrl.match(whitespaceEscapeCharsRegex); | ||
| } while (charsToDecode && charsToDecode.length > 0); | ||
@@ -43,0 +61,0 @@ const sanitizedUrl = decodedUrl; |
21452
9.2%383
15.02%