diff --git a/extension/js/common/platform/xss.ts b/extension/js/common/platform/xss.ts index 20cc682b07d..ecda2a5e2ec 100644 --- a/extension/js/common/platform/xss.ts +++ b/extension/js/common/platform/xss.ts @@ -47,7 +47,7 @@ export class Xss { 'col', ]; private static ADD_ATTR = ['email', 'page', 'addurltext', 'longid', 'index', 'target', 'fingerprint', 'cryptup-data']; - private static FORBID_ATTR = ['background']; + private static FORBID_ATTR = ['background', 'srcset']; private static HREF_REGEX_CACHE: RegExp | undefined; private static EMOJI_REGEX = /(?![*#0-9]+)[\p{Emoji}\p{Emoji_Modifier}\p{Emoji_Component}\p{Emoji_Modifier_Base}\p{Emoji_Presentation}]/gu; /* eslint-disable @typescript-eslint/naming-convention */ @@ -201,6 +201,11 @@ export class Xss { } else if (!src) { img.remove(); // src that exists but is null is suspicious } else if (imgHandling === 'IMG-KEEP' && checkValidURL(src)) { + const pathname = new URL(src).pathname.toLowerCase(); + if (pathname.includes('/logout') || pathname.includes('/signout')) { + img.remove(); + return; + } // replace remote image with remote_image_container const remoteImgEl = `
diff --git a/test/source/tests/browser-unit-tests/unit-Xss.js b/test/source/tests/browser-unit-tests/unit-Xss.js index 8b95ac0bf8c..c4ef7f46498 100644 --- a/test/source/tests/browser-unit-tests/unit-Xss.js +++ b/test/source/tests/browser-unit-tests/unit-Xss.js @@ -79,3 +79,42 @@ BROWSER_UNIT_TEST_NAME(`Xss.htmlSanitizeKeepBasicTags strips url() in CSS`); } return 'pass'; })(); + +BROWSER_UNIT_TEST_NAME(`Xss.htmlSanitizeKeepBasicTags strips srcset attribute from img`); +(async () => { + const dirty = ``; + const clean = Xss.htmlSanitizeKeepBasicTags(dirty, 'IMG-KEEP'); + if (/srcset/i.test(clean)) { + throw Error(`srcset was not stripped from sanitized HTML: ${clean}`); + } + if (!/src="cid:test-image"/.test(clean)) { + throw Error(`expected cid src to be preserved, got: ${clean}`); + } + return 'pass'; +})(); + +BROWSER_UNIT_TEST_NAME(`Xss.htmlSanitize (used for CID replacement) strips srcset attribute from img`); +(async () => { + const dirty = `inline`; + const clean = Xss.htmlSanitize(dirty); + if (/srcset/i.test(clean)) { + throw Error(`srcset was not stripped from sanitized HTML: ${clean}`); + } + if (!/src="cid:test-image"/.test(clean)) { + throw Error(`expected cid src to be preserved, got: ${clean}`); + } + return 'pass'; +})(); + +BROWSER_UNIT_TEST_NAME(`Xss.htmlSanitizeKeepBasicTags keeps srcset-less inline images and gates remote src`); +(async () => { + const dirty = ``; + const clean = Xss.htmlSanitizeKeepBasicTags(dirty, 'IMG-KEEP'); + if (/srcset/i.test(clean)) { + throw Error(`srcset was not stripped from sanitized HTML: ${clean}`); + } + if (!/remote_image_container/.test(clean)) { + throw Error(`expected remote src to be replaced with remote_image_container, got: ${clean}`); + } + return 'pass'; +})();