diff --git a/app/assets/javascripts/lib/dompurify.js b/app/assets/javascripts/lib/dompurify.js index 3861007d64640a3a72faed0ab0a8214fd234c0e8..f5038c5a62ff6c621236e780216cf9334ab728f2 100644 --- a/app/assets/javascripts/lib/dompurify.js +++ b/app/assets/javascripts/lib/dompurify.js @@ -125,6 +125,18 @@ addHook('beforeSanitizeAttributes', (node, _, config) => { } }); +// Permit "title", "data-name" and "data-unicode-version" attributes on +// (when allowed), even when ALLOW_DATA_ATTR is false. +addHook('uponSanitizeAttribute', (node, hookEvent) => { + if ( + node.tagName === 'GL-EMOJI' && + ['title', 'data-name', 'data-unicode-version'].includes(hookEvent.attrName) + ) { + // eslint-disable-next-line no-param-reassign + hookEvent.forceKeepAttr = true; + } +}); + addHook('afterSanitizeAttributes', (node, _, config) => { if (node.tagName === 'A' && node.hasAttribute(TEMPORARY_ATTRIBUTE)) { node.setAttribute('target', node.getAttribute(TEMPORARY_ATTRIBUTE)); diff --git a/lib/banzai/pipeline/gfm_pipeline.rb b/lib/banzai/pipeline/gfm_pipeline.rb index 1933119126bd8d69100447000427589c27bb79ae..b9ef83eb498fb4ad697fc4099b742ed97111c1ab 100644 --- a/lib/banzai/pipeline/gfm_pipeline.rb +++ b/lib/banzai/pipeline/gfm_pipeline.rb @@ -12,12 +12,15 @@ class GfmPipeline < BasePipeline def self.filters @filters ||= FilterArray[ Filter::CodeLanguageFilter, - Filter::JsonTableFilter, # process before sanitization + Filter::JsonTableFilter, Filter::PlantumlFilter, - # Must always be before the SanitizationFilter/SanitizeLinkFilter to prevent XSS attacks Filter::SpacedLinkFilter, + # ======== Sanitization boundary ======== + # Items above this point must not be moved below this point, as they depend + # on running before SanitizationFilter and SanitizeLinkFilter for safety. Filter::SanitizationFilter, Filter::SanitizeLinkFilter, + # ======================================= Filter::KrokiFilter, Filter::GollumTagsFilter, Filter::WikiLinkGollumFilter, diff --git a/spec/frontend/lib/dompurify_spec.js b/spec/frontend/lib/dompurify_spec.js index 9178aa65689d3ce6cbff0b740fedad30ae139854..f475c1288efa3db835f984e6d8af409458e0872e 100644 --- a/spec/frontend/lib/dompurify_spec.js +++ b/spec/frontend/lib/dompurify_spec.js @@ -231,4 +231,17 @@ describe('~/lib/dompurify', () => { expect(el.hasAttribute('rel')).toBe(false); }); }); + + describe('gl-emoji tags', () => { + it('does not remove the title, data-name, or data-unicode-version attributes', () => { + const html = `👍`; + expect(sanitize(html)).toBe(html); + }); + + it('does not remove the data-name or data-unicode-version attributes even when ALLOW_DATA_ATTR is false', () => { + const input = `👍`; + const expected = `👍`; + expect(sanitize(input, { ...defaultConfig, ALLOW_DATA_ATTR: false })).toBe(expected); + }); + }); }); diff --git a/spec/lib/banzai/filter/json_table_filter_spec.rb b/spec/lib/banzai/filter/json_table_filter_spec.rb index 799a3303a350c7a32af5012f7d6f9bca0a31c873..87a5245a3bece53d41113d2de0632d5a390e2fe2 100644 --- a/spec/lib/banzai/filter/json_table_filter_spec.rb +++ b/spec/lib/banzai/filter/json_table_filter_spec.rb @@ -23,7 +23,7 @@ ], "items": [ { - "starts_at": "_2024-10-07_" + "starts_at": "_2024-10-07_ :white_check_mark: 👍" }, { "url": "https://example.com/page2.html" @@ -50,7 +50,8 @@ - 2024-10-07 + + 2024-10-07 :white_check_mark: 👍