Socket
Socket
Sign inDemoInstall

@braintree/sanitize-url

Package Overview
Dependencies
Maintainers
1
Versions
25
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@braintree/sanitize-url - npm Package Compare versions

Comparing version 5.0.1 to 5.0.2

4

CHANGELOG.md

@@ -0,1 +1,5 @@

# 5.0.2
- Fix issue where certain invisible white space characters were not being sanitized (#35)
# 5.0.1

@@ -2,0 +6,0 @@

4

dist/index.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.sanitizeUrl = void 0;
var invalidProtocolRegex = /^(%20|\s)*(javascript|data|vbscript)/im;
var ctrlCharactersRegex = /[\u0000-\u001F\u007F-\u009F]/gim;
var invalidProtocolRegex = /^([^\w]*)(javascript|data|vbscript)/im;
var ctrlCharactersRegex = /[\u0000-\u001F\u007F-\u009F\u2000-\u200D\uFEFF]/gim;
var urlSchemeRegex = /^([^:]+):/gm;

@@ -7,0 +7,0 @@ var relativeFirstCharacters = [".", "/"];

{
"name": "@braintree/sanitize-url",
"version": "5.0.1",
"version": "5.0.2",
"description": "A url sanitizer",

@@ -27,12 +27,13 @@ "main": "dist/index.js",

"devDependencies": {
"@types/jest": "^26.0.19",
"chai": "^4.1.0",
"eslint": "^7.17.0",
"@types/jest": "^26.0.23",
"chai": "^4.3.4",
"eslint": "^7.27.0",
"eslint-config-braintree": "^5.0.0-typescript-prep-rc.18",
"jest": "^26.6.3",
"prettier": "^2.2.1",
"ts-jest": "^26.4.4",
"typescript": "^4.1.3"
"jest": "^27.0.3",
"prettier": "^2.3.0",
"ts-jest": "^27.0.2",
"typescript": "^4.3.2"
},
"jest": {
"testEnvironment": "jsdom",
"preset": "ts-jest",

@@ -39,0 +40,0 @@ "globals": {

@@ -5,111 +5,3 @@ /* eslint-disable no-script-url */

describe("sanitizeUrl", () => {
it("replaces javascript urls with about:blank", () => {
expect(sanitizeUrl("javascript:alert(document.domain)")).toBe(
"about:blank"
);
});
it("disregards capitalization for JavaScript urls", () => {
expect(sanitizeUrl("jAvasCrIPT:alert(document.domain)")).toBe(
"about:blank"
);
});
it("ignores ctrl characters in javascript urls", () => {
expect(
sanitizeUrl(decodeURIComponent("JaVaScRiP%0at:alert(document.domain)"))
).toBe("about:blank");
});
it("replaces javascript urls with about:blank when javascript url begins with %20", () => {
expect(sanitizeUrl("%20%20%20%20javascript:alert(document.domain)")).toBe(
"about:blank"
);
});
it("replaces javascript urls with about:blank when javascript url begins with s", () => {
expect(sanitizeUrl(" javascript:alert(document.domain)")).toBe(
"about:blank"
);
});
it("does not replace javascript: if it is not in the scheme of the URL", () => {
expect(sanitizeUrl("http://example.com#myjavascript:foo")).toBe(
"http://example.com#myjavascript:foo"
);
});
it("replaces data urls with about:blank", () => {
expect(
sanitizeUrl(
"data:text/html;base64,PH%3Cscript%3Ealert(document.domain)%3C/script%3E"
)
).toBe("about:blank");
});
it("replaces data urls with about:blank when data url begins with %20", () => {
expect(
sanitizeUrl(
"%20%20%20%20data:text/html;base64,PH%3Cscript%3Ealert(document.domain)%3C/script%3E"
)
).toBe("about:blank");
});
it("replaces data urls with about:blank when data url begins with s", () => {
expect(
sanitizeUrl(
" data:text/html;base64,PH%3Cscript%3Ealert(document.domain)%3C/script%3E"
)
).toBe("about:blank");
});
it("disregards capitalization for data urls", () => {
expect(
sanitizeUrl(
"dAtA:text/html;base64,PH%3Cscript%3Ealert(document.domain)%3C/script%3E"
)
).toBe("about:blank");
});
it("ignores ctrl characters in data urls", () => {
expect(
sanitizeUrl(
decodeURIComponent(
"dat%0aa:text/html;base64,PH%3Cscript%3Ealert(document.domain)%3C/script%3E"
)
)
).toBe("about:blank");
});
it("replaces VBscript urls with about:blank", () => {
expect(sanitizeUrl("vbscript:msgbox('XSS')")).toBe("about:blank");
});
it("disregards capitalization for VBscript urls", () => {
expect(sanitizeUrl("vbScrIpT:mSGBOX('XSS')")).toBe("about:blank");
});
it("ignores ctrl characters in VBscript urls", () => {
expect(sanitizeUrl(decodeURIComponent("VbScRiP%0at:msgbox('XSS')"))).toBe(
"about:blank"
);
});
it("replaces VBscript urls with about:blank when VBscript url begins with %20", () => {
expect(sanitizeUrl("%20%20%20%20vbscript:msgbox('XSS')")).toBe(
"about:blank"
);
});
it("replaces VBScript urls with about:blank when VBscript url begins with s", () => {
expect(sanitizeUrl(" vbscript:msgbox('XSS')")).toBe("about:blank");
});
it("does not replace VBscript: if it is not in the scheme of the URL", () => {
expect(sanitizeUrl("http://example.com#whatisvbscript:foo")).toBe(
"http://example.com#whatisvbscript:foo"
);
});
it("does not alter http URLs", () => {
it("does not alter http URLs with alphanumeric characters", () => {
expect(sanitizeUrl("http://example.com/path/to:something")).toBe(

@@ -120,3 +12,3 @@ "http://example.com/path/to:something"

it("does not alter http URLs with ports", () => {
it("does not alter http URLs with ports with alphanumeric characters", () => {
expect(sanitizeUrl("http://example.com:4567/path/to:something")).toBe(

@@ -127,7 +19,7 @@ "http://example.com:4567/path/to:something"

it("does not alter https URLs", () => {
it("does not alter https URLs with alphanumeric characters", () => {
expect(sanitizeUrl("https://example.com")).toBe("https://example.com");
});
it("does not alter https URLs with ports", () => {
it("does not alter https URLs with ports with alphanumeric characters", () => {
expect(sanitizeUrl("https://example.com:4567/path/to:something")).toBe(

@@ -138,11 +30,11 @@ "https://example.com:4567/path/to:something"

it("does not alter relative-path reference URLs", () => {
it("does not alter relative-path reference URLs with alphanumeric characters", () => {
expect(sanitizeUrl("./path/to/my.json")).toBe("./path/to/my.json");
});
it("does not alter absolute-path reference URLs", () => {
it("does not alter absolute-path reference URLs with alphanumeric characters", () => {
expect(sanitizeUrl("/path/to/my.json")).toBe("/path/to/my.json");
});
it("does not alter protocol-less network-path URLs", () => {
it("does not alter protocol-less network-path URLs with alphanumeric characters", () => {
expect(sanitizeUrl("//google.com/robots.txt")).toBe(

@@ -153,7 +45,7 @@ "//google.com/robots.txt"

it("does not alter protocol-less URLs", () => {
it("does not alter protocol-less URLs with alphanumeric characters", () => {
expect(sanitizeUrl("www.example.com")).toBe("www.example.com");
});
it("does not alter deep-link urls", () => {
it("does not alter deep-link urls with alphanumeric characters", () => {
expect(sanitizeUrl("com.braintreepayments.demo://example")).toBe(

@@ -164,3 +56,3 @@ "com.braintreepayments.demo://example"

it("does not alter mailto urls", () => {
it("does not alter mailto urls with alphanumeric characters", () => {
expect(sanitizeUrl("mailto:test@example.com?subject=hello+world")).toBe(

@@ -183,6 +75,6 @@ "mailto:test@example.com?subject=hello+world"

it("should strip out control chars", () => {
expect(sanitizeUrl("www.example.com/\u0000\u001F\x00\x1F")).toBe(
"www.example.com/"
);
it("strips out ctrl chars", () => {
expect(
sanitizeUrl("www.example.com/\u200D\u0000\u001F\x00\x1F\uFEFFfoo")
).toBe("www.example.com/foo");
});

@@ -195,2 +87,4 @@

it("replaces null values with about:blank", () => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
expect(sanitizeUrl(null)).toBe("about:blank");

@@ -208,2 +102,83 @@ });

});
describe("invalid protocols", () => {
describe.each(["javascript", "data", "vbscript"])("%s", (protocol) => {
it(`replaces ${protocol} urls with about:blank`, () => {
expect(sanitizeUrl(`${protocol}:alert(document.domain)`)).toBe(
"about:blank"
);
});
it(`allows ${protocol} urls that start with a letter prefix`, () => {
expect(sanitizeUrl(`not_${protocol}:alert(document.domain)`)).toBe(
`not_${protocol}:alert(document.domain)`
);
});
it(`disallows ${protocol} urls that start with non-\w characters as a suffix for the protocol`, () => {
expect(sanitizeUrl(`&!*${protocol}:alert(document.domain)`)).toBe(
"about:blank"
);
});
it(`disregards capitalization for ${protocol} urls`, () => {
// upper case every other letter in protocol name
const mixedCapitalizationProtocol = protocol
.split("")
.map((character, index) => {
if (index % 2 === 0) {
return character.toUpperCase();
}
return character;
})
.join("");
expect(
sanitizeUrl(`${mixedCapitalizationProtocol}:alert(document.domain)`)
).toBe("about:blank");
});
it(`ignores invisible ctrl characters in ${protocol} urls`, () => {
const protocolWithControlCharacters = protocol
.split("")
.map((character, index) => {
if (index === 1) {
return character + "%EF%BB%BF%EF%BB%BF";
} else if (index === 2) {
return character + "%e2%80%8b";
}
return character;
})
.join("");
expect(
sanitizeUrl(
decodeURIComponent(
`${protocolWithControlCharacters}:alert(document.domain)`
)
)
).toBe("about:blank");
});
it(`replaces ${protocol} urls with about:blank when url begins with %20`, () => {
expect(
sanitizeUrl(
decodeURIComponent(`%20%20%20%20${protocol}:alert(document.domain)`)
)
).toBe("about:blank");
});
it(`replaces ${protocol} urls with about:blank when ${protocol} url begins with spaces`, () => {
expect(sanitizeUrl(` ${protocol}:alert(document.domain)`)).toBe(
"about:blank"
);
});
it(`does not replace ${protocol}: if it is not in the scheme of the URL`, () => {
expect(sanitizeUrl(`http://example.com#${protocol}:foo`)).toBe(
`http://example.com#${protocol}:foo`
);
});
});
});
});

@@ -1,3 +0,4 @@

const invalidProtocolRegex = /^(%20|\s)*(javascript|data|vbscript)/im;
const ctrlCharactersRegex = /[\u0000-\u001F\u007F-\u009F]/gim;
const invalidProtocolRegex = /^([^\w]*)(javascript|data|vbscript)/im;
const ctrlCharactersRegex =
/[\u0000-\u001F\u007F-\u009F\u2000-\u200D\uFEFF]/gim;
const urlSchemeRegex = /^([^:]+):/gm;

@@ -4,0 +5,0 @@ const relativeFirstCharacters = [".", "/"];

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc