Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/flat-buckets-doubt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@rocket.chat/gazzodown': patch
'@rocket.chat/meteor': patch
---

Fixes an issue that causes legitimate URLs to return '#' in links
8 changes: 2 additions & 6 deletions packages/gazzodown/src/elements/sanitizeUrl.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,6 @@ describe('sanitizeUrl', () => {
});
});

it('sanitizes malformed URLs', () => {
expect(sanitizeUrl('ht^tp://broken')).toBe('#');
});

it('sanitizes empty string', () => {
expect(sanitizeUrl('')).toBe('#');
});
Expand All @@ -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');
});
});
16 changes: 13 additions & 3 deletions packages/gazzodown/src/elements/sanitizeUrl.ts
Original file line number Diff line number Diff line change
@@ -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 '#';
}
Expand Down
Loading