From ba0cbd32657365abc2a10e50285e02b4e34bf674 Mon Sep 17 00:00:00 2001 From: Julio Araujo Date: Wed, 2 Jul 2025 15:20:44 +0200 Subject: [PATCH] fix: change sanitizeUrl to handle URLs without a protocol schema (#36317) --- .changeset/flat-buckets-doubt.md | 6 ++++++ .../gazzodown/src/elements/sanitizeUrl.spec.ts | 8 ++------ packages/gazzodown/src/elements/sanitizeUrl.ts | 16 +++++++++++++--- 3 files changed, 21 insertions(+), 9 deletions(-) create mode 100644 .changeset/flat-buckets-doubt.md diff --git a/.changeset/flat-buckets-doubt.md b/.changeset/flat-buckets-doubt.md new file mode 100644 index 00000000000..56238224bac --- /dev/null +++ b/.changeset/flat-buckets-doubt.md @@ -0,0 +1,6 @@ +--- +'@rocket.chat/gazzodown': patch +'@rocket.chat/meteor': patch +--- + +Fixes an issue that causes legitimate URLs to return '#' in links diff --git a/packages/gazzodown/src/elements/sanitizeUrl.spec.ts b/packages/gazzodown/src/elements/sanitizeUrl.spec.ts index b266b48da71..feea965ccee 100644 --- a/packages/gazzodown/src/elements/sanitizeUrl.spec.ts +++ b/packages/gazzodown/src/elements/sanitizeUrl.spec.ts @@ -95,10 +95,6 @@ describe('sanitizeUrl', () => { }); }); - it('sanitizes malformed URLs', () => { - expect(sanitizeUrl('ht^tp://broken')).toBe('#'); - }); - it('sanitizes empty string', () => { expect(sanitizeUrl('')).toBe('#'); }); @@ -107,7 +103,7 @@ describe('sanitizeUrl', () => { expect(sanitizeUrl('JAVASCRIPT:alert(1)')).toBe('#'); }); - it('sanitizes nonsense input', () => { - expect(sanitizeUrl('💣💥🤯')).toBe('#'); + it('allows bare domain names', () => { + expect(sanitizeUrl('example.com/page')).toBe('//example.com/page'); }); }); diff --git a/packages/gazzodown/src/elements/sanitizeUrl.ts b/packages/gazzodown/src/elements/sanitizeUrl.ts index 49beaf4822f..ac26af22c0b 100644 --- a/packages/gazzodown/src/elements/sanitizeUrl.ts +++ b/packages/gazzodown/src/elements/sanitizeUrl.ts @@ -1,8 +1,18 @@ export const sanitizeUrl = (href: string) => { + if (!href) { + return '#'; + } + try { - const url = new URL(href); - const dangerousProtocols = ['javascript:', 'data:', 'vbscript:']; - return dangerousProtocols.includes(url.protocol.toLowerCase()) ? '#' : url.href; + const hasProtocol = /^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(href); + + if (hasProtocol) { + const url = new URL(href); + const dangerousProtocols = ['javascript:', 'data:', 'vbscript:']; + return dangerousProtocols.includes(url.protocol.toLowerCase()) ? '#' : url.href; + } + + return `//${href}`; } catch { return '#'; }