Skip to content

Commit

Permalink
li-38822 fix: handle whitespace escapes
Browse files Browse the repository at this point in the history
  • Loading branch information
ibooker committed May 6, 2024
1 parent 0d5140d commit 1c0be2b
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 1 deletion.
13 changes: 13 additions & 0 deletions src/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,19 @@ describe("sanitizeUrl", () => {
).toBe("https://example.com/javascript:alert('XSS')");
});

it("removes whitespace escape sequences", () => {
const attackVectors = [
"javascri\npt:alert('xss')",
"javascri\rpt:alert('xss')",
"javascri\tpt:alert('xss')",
"javascrip\x74t:alert('XSS')",
];

attackVectors.forEach((vector) => {
expect(sanitizeUrl(vector)).toBe(BLANK_URL);
});
});

describe("invalid protocols", () => {
describe.each(["javascript", "data", "vbscript"])("%s", (protocol) => {
it(`replaces ${protocol} urls with ${BLANK_URL}`, () => {
Expand Down
1 change: 1 addition & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ export const htmlCtrlEntityRegex = /&(newline|tab);/gi;
export const ctrlCharactersRegex =
/[\u0000-\u001F\u007F-\u009F\u2000-\u200D\uFEFF]/gim;
export const urlSchemeRegex = /^.+(:|:)/gim;
export const whitespaceEscapeChars = /\\[nrt]/g;
export const relativeFirstCharacters = [".", "/"];
export const BLANK_URL = "about:blank";
5 changes: 4 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
invalidProtocolRegex,
relativeFirstCharacters,
urlSchemeRegex,
whitespaceEscapeChars,
} from "./constants";

function isRelativeUrlWithoutProtocol(url: string): boolean {
Expand All @@ -30,11 +31,13 @@ export function sanitizeUrl(url?: string): string {
decodedUrl = decodeHtmlCharacters(decodedUrl)
.replace(htmlCtrlEntityRegex, "")
.replace(ctrlCharactersRegex, "")
.replace(whitespaceEscapeChars, "")
.trim();
charsToDecode =
decodedUrl.match(ctrlCharactersRegex) ||
decodedUrl.match(htmlEntitiesRegex) ||
decodedUrl.match(htmlCtrlEntityRegex);
decodedUrl.match(htmlCtrlEntityRegex) ||
decodedUrl.match(whitespaceEscapeChars);
} while (charsToDecode && charsToDecode.length > 0);
const sanitizedUrl = decodedUrl;
if (!sanitizedUrl) {
Expand Down

0 comments on commit 1c0be2b

Please sign in to comment.