diff --git a/craft/src/components/basic/HtmlBlock.security.test.ts b/craft/src/components/basic/HtmlBlock.security.test.ts index ddfcca7..079fd51 100644 --- a/craft/src/components/basic/HtmlBlock.security.test.ts +++ b/craft/src/components/basic/HtmlBlock.security.test.ts @@ -257,4 +257,43 @@ describe('purifyHtml -- Task 24: security properties on newly-allowed elements', ); expect(out).not.toContain('data:text/html'); }); + + test('review fix: data:image/*;base64, URIs now actually survive on poster/cite/href (dead-code regex bug)', () => { + // ALLOWED_URI_REGEXP used to put the data:image arm inside the group + // that gets a trailing `:` appended to every alternative, requiring a + // second colon after the one already in "base64," -- which no real + // data URI has, so the clause could never match anything. Confirm the + // fixed regex actually allows a real base64 image data URI through on + // ordinary URI-checked attributes (not just the DATA_URI_TAGS-covered + // src ones tested below). + const b64 = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII='; + const out = purifyHtml( + `` + + `
q` + + `img`, + ); + expect(out).toContain(`poster="data:image/png;base64,${b64}"`); + expect(out).toContain(`cite="data:image/png;base64,${b64}"`); + expect(out).toContain(`href="data:image/png;base64,${b64}"`); + }); + + test('documented reality: data: on img/video/audio/source src is mimetype-blind (DOMPurify DATA_URI_TAGS bypasses ALLOWED_URI_REGEXP)', () => { + // This is NOT gated by ALLOWED_URI_REGEXP at all -- DOMPurify has its + // own internal DATA_URI_TAGS allow-list (img, video, audio, source, + // image, track) that accepts ANY data: URI on the `src` attribute of + // those tags regardless of declared mimetype, before our regex is ever + // consulted. Acceptable because none of those tags execute their src + // as a document/script context in mainstream browsers -- the sink + // doesn't execute. Pinned here so a future DOMPurify version change to + // DATA_URI_TAGS shows up as a failing test, not a surprise in + // production.