Skip to content

Commit d4bdc89

Browse files
Fix html entity tab (#45)
* fix: correct urls that did not sanitize html encoded colons * fix: replace html encoded tabs * update CHANGELOG.md Co-authored-by: Blade Barringer <[email protected]>
1 parent b70161d commit d4bdc89

File tree

3 files changed

+18
-1
lines changed

3 files changed

+18
-1
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# CHANGELOG
22

3+
## unreleased
4+
5+
- Fix issue where urls in the form `javascript&colon;alert('xss');` were not properly sanitized
6+
- Fix issue where urls in the form `javasc&Tab;ript:alert('XSS');` were not properly sanitized
7+
38
## 6.0.0
49

510
**Breaking Changes**

src/__tests__/test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ describe("sanitizeUrl", () => {
100100
"&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29",
101101
"jav&#x09;ascript:alert('XSS');",
102102
" &#14; javascript:alert('XSS');",
103+
"javasc&Tab;ript: alert('XSS');",
103104
];
104105

105106
attackVectors.forEach((vector) => {
@@ -136,6 +137,15 @@ describe("sanitizeUrl", () => {
136137
);
137138
});
138139

140+
it(`disallows ${protocol} urls that use &colon; for the colon portion of the url`, () => {
141+
expect(sanitizeUrl(`${protocol}&colon;alert(document.domain)`)).toBe(
142+
"about:blank"
143+
);
144+
expect(sanitizeUrl(`${protocol}&COLON;alert(document.domain)`)).toBe(
145+
"about:blank"
146+
);
147+
});
148+
139149
it(`disregards capitalization for ${protocol} urls`, () => {
140150
// upper case every other letter in protocol name
141151
const mixedCapitalizationProtocol = protocol

src/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
const invalidProtocolRegex = /^([^\w]*)(javascript|data|vbscript)/im;
22
const htmlEntitiesRegex = /&#(\w+)(^\w|;)?/g;
3+
const htmlTabEntityRegex = /&tab;/gi;
34
const ctrlCharactersRegex =
45
/[\u0000-\u001F\u007F-\u009F\u2000-\u200D\uFEFF]/gim;
5-
const urlSchemeRegex = /^([^:]+):/gm;
6+
const urlSchemeRegex = /^.+(:|&colon;)/gim;
67
const relativeFirstCharacters = [".", "/"];
78

89
function isRelativeUrlWithoutProtocol(url: string): boolean {
@@ -11,6 +12,7 @@ function isRelativeUrlWithoutProtocol(url: string): boolean {
1112

1213
// adapted from https://stackoverflow.com/a/29824550/2601552
1314
function decodeHtmlCharacters(str: string) {
15+
str = str.replace(htmlTabEntityRegex, "&#9;");
1416
return str.replace(htmlEntitiesRegex, (match, dec) => {
1517
return String.fromCharCode(dec);
1618
});

0 commit comments

Comments
 (0)