Annotations: Allow target="_blank" (#106301)

Co-authored-by: Kristian Bremberg <kristian.bremberg@grafana.com>
This commit is contained in:
Adela Almasan
2025-07-11 15:19:40 +00:00
committed by GitHub
co-authored by Kristian Bremberg
parent 98995922f9
commit 40da94cf74
2 changed files with 29 additions and 0 deletions
@@ -55,6 +55,26 @@ describe('sanitize', () => {
const str = sanitize(html);
expect(str).toBe('');
});
describe('should sanitize anchors with target="_blank"', () => {
it('should add rel="noopener noreferrer" to target="_blank" links', () => {
const html = '<a href="https://example.com" target="_blank">Link</a>';
const str = sanitize(html);
expect(str).toBe('<a href="https://example.com" target="_blank" rel="noopener noreferrer">Link</a>');
});
it('should preserve existing rel attributes and add noopener noreferrer, if not already added', () => {
const html = '<a href="https://example.com" target="_blank" rel="external noreferrer">Link</a>';
const str = sanitize(html);
expect(str).toBe('<a href="https://example.com" target="_blank" rel="noopener noreferrer">Link</a>');
});
it('should not modify links without target="_blank"', () => {
const html = '<a href="https://example.com">Link</a>';
const str = sanitize(html);
expect(str).toBe('<a href="https://example.com">Link</a>');
});
});
});
describe('validatePath', () => {
@@ -56,13 +56,22 @@ const sanitizeTextPanelWhitelist = new xss.FilterXSS({
*/
export function sanitize(unsanitizedString: string): string {
try {
DOMPurify.addHook('afterSanitizeAttributes', (node) => {
if (node.tagName === 'A' && node.getAttribute('target') === '_blank') {
node.setAttribute('rel', 'noopener noreferrer');
}
});
return DOMPurify.sanitize(unsanitizedString, {
USE_PROFILES: { html: true },
FORBID_TAGS: ['form', 'input'],
ADD_ATTR: ['target'],
});
} catch (error) {
console.error('String could not be sanitized', unsanitizedString);
return escapeHtml(unsanitizedString);
} finally {
DOMPurify.removeHook('afterSanitizeAttributes');
}
}