import { DefaultAllowlist, sanitizeHtml } from '../../../src/util/sanitizer.js'
describe('Sanitizer', () => {
describe('sanitizeHtml', () => {
it('should return the same on empty string', () => {
const empty = ''
const result = sanitizeHtml(empty, DefaultAllowlist, null)
expect(result).toEqual(empty)
})
it('should retain tags with valid URLs', () => {
const validUrls = [
'',
'http://abc',
'HTTP://abc',
'https://abc',
'HTTPS://abc',
'ftp://abc',
'FTP://abc',
'mailto:me@example.com',
'MAILTO:me@example.com',
'tel:123-123-1234',
'TEL:123-123-1234',
'sip:me@example.com',
'SIP:me@example.com',
'#anchor',
'/page1.md',
'http://JavaScript/my.js',
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/', // Truncated.
'data:video/webm;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/',
'data:audio/opus;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/',
'unknown-scheme:abc'
]
for (const url of validUrls) {
const template = [
'
'
].join('')
const result = sanitizeHtml(template, DefaultAllowlist, null)
expect(result).toContain(`href="${url}"`)
}
})
it('should sanitize template by removing tags with XSS', () => {
const invalidUrls = [
// eslint-disable-next-line no-script-url
'javascript:alert(7)',
// eslint-disable-next-line no-script-url
'javascript:evil()',
// eslint-disable-next-line no-script-url
'JavaScript:abc',
' javascript:abc',
' \n Java\n Script:abc',
'javascript:',
'javascript:',
'j avascript:',
'javascript:',
'javascript:',
'jav ascript:alert();',
'jav\u0000ascript:alert();'
]
for (const url of invalidUrls) {
const template = [
''
].join('')
const result = sanitizeHtml(template, DefaultAllowlist, null)
expect(result).not.toContain(`href="${url}"`)
}
})
it('should sanitize template and work with multiple regex', () => {
const template = [
''
].join('')
const myDefaultAllowList = DefaultAllowlist
// With the default allow list
let result = sanitizeHtml(template, myDefaultAllowList, null)
// `data-foo` won't be present
expect(result).not.toContain('data-foo="bar"')
// Add the following regex too
myDefaultAllowList['*'].push(/^data-foo/)
result = sanitizeHtml(template, myDefaultAllowList, null)
expect(result).not.toContain('href="javascript:alert(7)') // This is in the default list
expect(result).toContain('aria-label="This is a link"') // This is in the default list
expect(result).toContain('data-foo="bar"') // We explicitly allow this
})
it('should allow aria attributes and safe attributes', () => {
const template = [
'',
' Some content',
'
'
].join('')
const result = sanitizeHtml(template, DefaultAllowlist, null)
expect(result).toContain('aria-pressed')
expect(result).toContain('class="test"')
})
it('should remove tags not in allowlist', () => {
const template = [
'',
' ',
'
'
].join('')
const result = sanitizeHtml(template, DefaultAllowlist, null)
expect(result).not.toContain('