import { sanitize } from '~/lib/dompurify'; // GDK const rootGon = { sprite_file_icons: '/assets/icons-123a.svg', sprite_icons: '/assets/icons-456b.svg', }; // Production const absoluteGon = { sprite_file_icons: `${window.location.protocol}//${window.location.hostname}/assets/icons-123a.svg`, sprite_icons: `${window.location.protocol}//${window.location.hostname}/assets/icons-456b.svg`, }; const expectedSanitized = ''; const safeUrls = { root: Object.values(rootGon).map(url => `${url}#ellipsis_h`), absolute: Object.values(absoluteGon).map(url => `${url}#ellipsis_h`), }; const unsafeUrls = [ '/an/evil/url', '../../../evil/url', 'https://evil.url/assets/icons-123a.svg', 'https://evil.url/assets/icons-456b.svg', `https://evil.url/${rootGon.sprite_icons}`, `https://evil.url/${rootGon.sprite_file_icons}`, `https://evil.url/${absoluteGon.sprite_icons}`, `https://evil.url/${absoluteGon.sprite_file_icons}`, ]; describe('~/lib/dompurify', () => { let originalGon; it('uses local configuration when given', () => { // As dompurify uses a "Persistent Configuration", it might // ignore config, this check verifies we respect // https://github.com/cure53/DOMPurify#persistent-configuration expect(sanitize('
', { ALLOWED_TAGS: [] })).toBe(''); expect(sanitize('', { ALLOWED_TAGS: [] })).toBe(''); }); describe.each` type | gon ${'root'} | ${rootGon} ${'absolute'} | ${absoluteGon} `('when gon contains $type icon urls', ({ type, gon }) => { beforeAll(() => { originalGon = window.gon; window.gon = gon; }); afterAll(() => { window.gon = originalGon; }); it('allows no href attrs', () => { const htmlHref = ``; expect(sanitize(htmlHref)).toBe(htmlHref); }); it.each(safeUrls[type])('allows safe URL %s', url => { const htmlHref = ``; expect(sanitize(htmlHref)).toBe(htmlHref); const htmlXlink = ``; expect(sanitize(htmlXlink)).toBe(htmlXlink); }); it.each(unsafeUrls)('sanitizes unsafe URL %s', url => { const htmlHref = ``; const htmlXlink = ``; expect(sanitize(htmlHref)).toBe(expectedSanitized); expect(sanitize(htmlXlink)).toBe(expectedSanitized); }); }); describe('when gon does not contain icon urls', () => { beforeAll(() => { originalGon = window.gon; window.gon = {}; }); afterAll(() => { window.gon = originalGon; }); it.each([...safeUrls.root, ...safeUrls.absolute, ...unsafeUrls])('sanitizes URL %s', url => { const htmlHref = ``; const htmlXlink = ``; expect(sanitize(htmlHref)).toBe(expectedSanitized); expect(sanitize(htmlXlink)).toBe(expectedSanitized); }); }); });