Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
5 changes: 5 additions & 0 deletions .changeset/fix-remove-rel-target-outgoing-links.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
default: patch
---

Remove target and rel attributes from outgoing html links.
2 changes: 1 addition & 1 deletion src/app/components/editor/output.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ const elementToCustomHtml = (
case BlockType.Link:
return testMatrixTo(node.href)
? sanitizeText(node.href)
: `<a href="${encodeURI(node.href)}" target="_blank" rel="noreferrer noopener">${children}</a>`;
: `<a href="${encodeURI(node.href)}">${children}</a>`;
case BlockType.Command:
return `/${sanitizeText(node.command)}`;
default:
Expand Down
2 changes: 2 additions & 0 deletions src/app/plugins/markdown/markdownToHtml.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ describe('markdownToHtml', () => {
it('converts links', () => {
const result = markdownToHtml('[link](https://example.com)');
expect(result).toContain('<a href="https://example.com"');
expect(result).not.toContain('target=');
expect(result).not.toContain('rel=');
});

it('converts spoiler syntax', () => {
Expand Down
11 changes: 2 additions & 9 deletions src/app/plugins/markdown/markdownToHtml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,12 +154,8 @@ export function markdownToHtml(markdown: string, options?: MarkdownToHtmlOptions

const allowlistedHtml = escapeNonAllowlistedHtmlTags(unescapedInline);

// Force all links to open in a new tab, validate <ol start>.
// Validate <ol start> after sanitization.
DOMPurify.addHook('afterSanitizeAttributes', (node) => {
if (node.tagName === 'A' && node.getAttribute('href')) {
node.setAttribute('target', '_blank');
node.setAttribute('rel', 'noreferrer noopener');
}
if (node.tagName === 'OL') {
const start = node.getAttribute('start');
if (start !== null && !ORDERED_LIST_START_REGEX.test(start)) {
Expand All @@ -177,8 +173,6 @@ export function markdownToHtml(markdown: string, options?: MarkdownToHtmlOptions
'title',
'height',
'width',
'target',
'rel',
'data-mx-emoticon',
'data-mx-spoiler',
'data-mx-maths',
Expand All @@ -194,9 +188,8 @@ export function markdownToHtml(markdown: string, options?: MarkdownToHtmlOptions
// Ensure these safe attrs survive sanitization even when the input HTML
// originates from markdown-embedded tags (e.g. custom emoji <img>).
// `start` must be URI-safe or DOMPurify drops it when ALLOWED_URI_REGEXP is set.
ADD_ATTR: ['target', 'rel', 'height', 'width'],
ADD_ATTR: ['height', 'width'],
ADD_URI_SAFE_ATTR: ['start'],
// Force all links to have safe rel attribute
FORCE_BODY: false,
ALLOWED_URI_REGEXP: /^(?:https?|ftp|mailto|magnet|mxc):/i,
});
Expand Down
2 changes: 1 addition & 1 deletion src/app/utils/sanitize.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ describe('sanitizeCustomHtml', () => {
expect(result).toContain('data-mx-maths="x"');
expect(result).toContain('data-md="**"');
expect(result).toContain('href="https://example.com"');
expect(result).toContain('target="_blank"');
expect(result).toContain('data-md="[]()"');
expect(result).not.toContain('target=');
expect(result).not.toContain('rel=');
expect(result).toContain('<ol start="2" data-md="1.">');
expect(result).not.toContain('type=');
Expand Down
2 changes: 1 addition & 1 deletion src/app/utils/sanitize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const permittedHtmlTags = [

const permittedTagToAttributes = {
span: ['data-mx-bg-color', 'data-mx-color', 'data-mx-spoiler', 'data-mx-maths', 'data-md'],
a: ['target', 'href', 'data-md'],
a: ['href', 'data-md'],
img: ['width', 'height', 'alt', 'title', 'src', 'data-mx-emoticon'], // data-mx-emoticon is for MSC2545
ol: ['start', 'data-md'],
ul: ['data-md'],
Expand Down
Loading