From b24a18e4069afb6fbd61b71c3ce5d6e7eeb1cfdf Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Fri, 30 Jul 2021 18:30:01 +0200 Subject: [PATCH 1/2] fix(techdocs-plugin): do not sanitize safe head links Signed-off-by: Camila Belo --- .changeset/chocolate-cake.md | 5 +++ .../reader/transformers/sanitizeDOM.test.ts | 35 +++++++++++++++++++ .../src/reader/transformers/sanitizeDOM.ts | 21 +++++++++++ 3 files changed, 61 insertions(+) create mode 100644 .changeset/chocolate-cake.md diff --git a/.changeset/chocolate-cake.md b/.changeset/chocolate-cake.md new file mode 100644 index 0000000000..36abca944f --- /dev/null +++ b/.changeset/chocolate-cake.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Avoid sanitize safe links in the header of document pages. diff --git a/plugins/techdocs/src/reader/transformers/sanitizeDOM.test.ts b/plugins/techdocs/src/reader/transformers/sanitizeDOM.test.ts index 8e5b245941..66019fb74f 100644 --- a/plugins/techdocs/src/reader/transformers/sanitizeDOM.test.ts +++ b/plugins/techdocs/src/reader/transformers/sanitizeDOM.test.ts @@ -110,4 +110,39 @@ describe('sanitizeDOM', () => { expect(shadowDom.querySelectorAll('link').length).toEqual(1); }); + + describe('safe head links', () => { + let shadowDom: ShadowRoot; + + beforeEach(async () => { + shadowDom = await createTestShadowDom(FIXTURES.FIXTURE_STANDARD_PAGE, { + preTransformers: [sanitizeDOM()], + postTransformers: [], + }); + }); + + it('should not sanitize the techdocs css', async () => { + const techdocsCss = shadowDom.querySelector( + 'link[href$="main.fe0cca5b.min.css"]', + ); + const rel = techdocsCss!.getAttribute('rel'); + expect(rel).toBe('stylesheet'); + }); + + it('should not sanitize google fonts', async () => { + const googleFonts = shadowDom.querySelector( + 'link[href^="https://fonts.googleapis.com"]', + ); + const rel = googleFonts!.getAttribute('rel'); + expect(rel).toBe('stylesheet'); + }); + + it('should not sanitize gstatic fonts', async () => { + const gstaticFonts = shadowDom.querySelector( + 'link[href^="https://fonts.gstatic.com"]', + ); + const rel = gstaticFonts!.getAttribute('rel'); + expect(rel).toBe('preconnect'); + }); + }); }); diff --git a/plugins/techdocs/src/reader/transformers/sanitizeDOM.ts b/plugins/techdocs/src/reader/transformers/sanitizeDOM.ts index 84dea567a2..828c0eb052 100644 --- a/plugins/techdocs/src/reader/transformers/sanitizeDOM.ts +++ b/plugins/techdocs/src/reader/transformers/sanitizeDOM.ts @@ -14,11 +14,32 @@ * limitations under the License. */ +const TECHDOCS_CSS = /main\.[A-Fa-f0-9]{8}\.min\.css/; +const GOOGLE_FONTS = /fonts\.googleapis\.com/; +const GSTATIC_FONTS = /fonts\.gstatic\.com/; + +export const safeLinksHook = (node: Element) => { + if (node.nodeName && node.nodeName === 'LINK') { + const href = node.getAttribute('href') || ''; + if (href.match(TECHDOCS_CSS)) { + node.setAttribute('rel', 'stylesheet'); + } + if (href.match(GOOGLE_FONTS)) { + node.setAttribute('rel', 'stylesheet'); + } + if (href.match(GSTATIC_FONTS)) { + node.setAttribute('rel', 'preconnect'); + } + } + return node; +}; + import DOMPurify from 'dompurify'; import type { Transformer } from './transformer'; export const sanitizeDOM = (): Transformer => { return dom => { + DOMPurify.addHook('afterSanitizeAttributes', safeLinksHook); return DOMPurify.sanitize(dom.innerHTML, { ADD_TAGS: ['link'], FORBID_TAGS: ['style'], From db58cf06c24de1382e25f490f22bb5bd460addf7 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Tue, 3 Aug 2021 08:56:01 +0200 Subject: [PATCH 2/2] fix(techdocs-plugin): apply review suggestions - strict regex scope to avoid security issues - add techdocs prefix to the changeset file Signed-off-by: Camila Belo --- .../{chocolate-cake.md => techdocs-chocolate-cake.md} | 0 plugins/techdocs/src/reader/transformers/sanitizeDOM.ts | 6 +++--- 2 files changed, 3 insertions(+), 3 deletions(-) rename .changeset/{chocolate-cake.md => techdocs-chocolate-cake.md} (100%) diff --git a/.changeset/chocolate-cake.md b/.changeset/techdocs-chocolate-cake.md similarity index 100% rename from .changeset/chocolate-cake.md rename to .changeset/techdocs-chocolate-cake.md diff --git a/plugins/techdocs/src/reader/transformers/sanitizeDOM.ts b/plugins/techdocs/src/reader/transformers/sanitizeDOM.ts index 828c0eb052..73c3bd2237 100644 --- a/plugins/techdocs/src/reader/transformers/sanitizeDOM.ts +++ b/plugins/techdocs/src/reader/transformers/sanitizeDOM.ts @@ -14,9 +14,9 @@ * limitations under the License. */ -const TECHDOCS_CSS = /main\.[A-Fa-f0-9]{8}\.min\.css/; -const GOOGLE_FONTS = /fonts\.googleapis\.com/; -const GSTATIC_FONTS = /fonts\.gstatic\.com/; +const TECHDOCS_CSS = /main\.[A-Fa-f0-9]{8}\.min\.css$/; +const GOOGLE_FONTS = /^https:\/\/fonts\.googleapis\.com/; +const GSTATIC_FONTS = /^https:\/\/fonts\.gstatic\.com/; export const safeLinksHook = (node: Element) => { if (node.nodeName && node.nodeName === 'LINK') {