Skip to content

Commit 2c8abb9

Browse files
Johann-SXhmikosR
authored andcommitted
Add sanitize for tooltips and popovers html content.
On browsers that `createHTMLDocument` isn't available just return the unsafe HTML.
1 parent d4129df commit 2c8abb9

File tree

4 files changed

+361
-9
lines changed

4 files changed

+361
-9
lines changed

js/popover.js

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,25 @@
4545
var title = this.getTitle()
4646
var content = this.getContent()
4747

48-
$tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
49-
$tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
50-
this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
51-
](content)
48+
if (this.options.html) {
49+
var typeContent = typeof content
50+
51+
if (this.options.sanitize) {
52+
title = this.sanitizeHtml(title)
53+
54+
if (typeContent === 'string') {
55+
content = this.sanitizeHtml(content)
56+
}
57+
}
58+
59+
$tip.find('.popover-title').html(title)
60+
$tip.find('.popover-content').children().detach().end()[
61+
typeContent === 'string' ? 'html' : 'append'
62+
](content)
63+
} else {
64+
$tip.find('.popover-title').text(title)
65+
$tip.find('.popover-content').children().detach().end().text(content)
66+
}
5267

5368
$tip.removeClass('fade top bottom left right in')
5469

js/tests/unit/popover.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ $(function () {
190190
.bootstrapPopover({
191191
title: 'Test',
192192
content: 'Test',
193-
template: '<div class="popover foobar"><div class="arrow"></div><div class="inner"><h3 class="title"/><div class="content"><p/></div></div></div>'
193+
template: '<div class="popover foobar"><div class="arrow"></div><div class="inner"><h3 class="title"></h3><div class="content"><p></p></div></div></div>'
194194
})
195195
.one('shown.bs.popover', function () {
196196
assert.notEqual($('.popover').length, 0, 'popover was inserted')

js/tests/unit/tooltip.js

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1526,4 +1526,184 @@ $(function () {
15261526
}
15271527
})
15281528
})
1529+
1530+
QUnit.test('should disable sanitizer', function (assert) {
1531+
assert.expect(1)
1532+
1533+
var $trigger = $('<a href="#" rel="tooltip" data-trigger="click" title="Another tooltip"/>')
1534+
.appendTo('#qunit-fixture')
1535+
.bootstrapTooltip({
1536+
sanitize: false
1537+
})
1538+
1539+
var tooltip = $trigger.data('bs.tooltip')
1540+
assert.strictEqual(tooltip.options.sanitize, false)
1541+
})
1542+
1543+
QUnit.test('should sanitize template by removing disallowed tags', function (assert) {
1544+
if (!document.implementation || !document.implementation.createHTMLDocument) {
1545+
assert.expect(0)
1546+
1547+
return
1548+
}
1549+
1550+
assert.expect(1)
1551+
1552+
var $trigger = $('<a href="#" rel="tooltip" data-trigger="click" title="Another tooltip"/>')
1553+
.appendTo('#qunit-fixture')
1554+
.bootstrapTooltip({
1555+
template: [
1556+
'<div>',
1557+
' <script>console.log("oups script inserted")</script>',
1558+
' <span>Some content</span>',
1559+
'</div>'
1560+
].join('')
1561+
})
1562+
1563+
var tooltip = $trigger.data('bs.tooltip')
1564+
assert.strictEqual(tooltip.options.template.indexOf('script'), -1)
1565+
})
1566+
1567+
QUnit.test('should sanitize template by removing disallowed attributes', function (assert) {
1568+
if (!document.implementation || !document.implementation.createHTMLDocument) {
1569+
assert.expect(0)
1570+
1571+
return
1572+
}
1573+
1574+
assert.expect(1)
1575+
1576+
var $trigger = $('<a href="#" rel="tooltip" data-trigger="click" title="Another tooltip"/>')
1577+
.appendTo('#qunit-fixture')
1578+
.bootstrapTooltip({
1579+
template: [
1580+
'<div>',
1581+
' <img src="x" onError="alert(\'test\')">Some content</img>',
1582+
'</div>'
1583+
].join('')
1584+
})
1585+
1586+
var tooltip = $trigger.data('bs.tooltip')
1587+
assert.strictEqual(tooltip.options.template.indexOf('onError'), -1)
1588+
})
1589+
1590+
QUnit.test('should sanitize template by removing tags with XSS', function (assert) {
1591+
if (!document.implementation || !document.implementation.createHTMLDocument) {
1592+
assert.expect(0)
1593+
1594+
return
1595+
}
1596+
1597+
assert.expect(1)
1598+
1599+
var $trigger = $('<a href="#" rel="tooltip" data-trigger="click" title="Another tooltip"/>')
1600+
.appendTo('#qunit-fixture')
1601+
.bootstrapTooltip({
1602+
template: [
1603+
'<div>',
1604+
' <a href="javascript:alert(7)">Click me</a>',
1605+
' <span>Some content</span>',
1606+
'</div>'
1607+
].join('')
1608+
})
1609+
1610+
var tooltip = $trigger.data('bs.tooltip')
1611+
assert.strictEqual(tooltip.options.template.indexOf('javascript'), -1)
1612+
})
1613+
1614+
QUnit.test('should allow custom sanitization rules', function (assert) {
1615+
if (!document.implementation || !document.implementation.createHTMLDocument) {
1616+
assert.expect(0)
1617+
1618+
return
1619+
}
1620+
1621+
assert.expect(2)
1622+
1623+
var $trigger = $('<a href="#" rel="tooltip" data-trigger="click" title="Another tooltip"/>')
1624+
.appendTo('#qunit-fixture')
1625+
.bootstrapTooltip({
1626+
template: [
1627+
'<a href="javascript:alert(7)">Click me</a>',
1628+
'<span>Some content</span>'
1629+
].join(''),
1630+
whiteList: {
1631+
span: null
1632+
}
1633+
})
1634+
1635+
var tooltip = $trigger.data('bs.tooltip')
1636+
1637+
assert.strictEqual(tooltip.options.template.indexOf('<a'), -1)
1638+
assert.ok(tooltip.options.template.indexOf('span') !== -1)
1639+
})
1640+
1641+
QUnit.test('should allow passing a custom function for sanitization', function (assert) {
1642+
if (!document.implementation || !document.implementation.createHTMLDocument) {
1643+
assert.expect(0)
1644+
1645+
return
1646+
}
1647+
1648+
assert.expect(1)
1649+
1650+
var $trigger = $('<a href="#" rel="tooltip" data-trigger="click" title="Another tooltip"/>')
1651+
.appendTo('#qunit-fixture')
1652+
.bootstrapTooltip({
1653+
template: [
1654+
'<span>Some content</span>'
1655+
].join(''),
1656+
sanitizeFn: function (input) {
1657+
return input
1658+
}
1659+
})
1660+
1661+
var tooltip = $trigger.data('bs.tooltip')
1662+
1663+
assert.ok(tooltip.options.template.indexOf('span') !== -1)
1664+
})
1665+
1666+
QUnit.test('should allow passing aria attributes', function (assert) {
1667+
if (!document.implementation || !document.implementation.createHTMLDocument) {
1668+
assert.expect(0)
1669+
1670+
return
1671+
}
1672+
1673+
assert.expect(1)
1674+
1675+
var $trigger = $('<a href="#" rel="tooltip" data-trigger="click" title="Another tooltip"/>')
1676+
.appendTo('#qunit-fixture')
1677+
.bootstrapTooltip({
1678+
template: [
1679+
'<span aria-pressed="true">Some content</span>'
1680+
].join('')
1681+
})
1682+
1683+
var tooltip = $trigger.data('bs.tooltip')
1684+
1685+
assert.ok(tooltip.options.template.indexOf('aria-pressed') !== -1)
1686+
})
1687+
1688+
QUnit.test('should not take into account sanitize in data attributes', function (assert) {
1689+
if (!document.implementation || !document.implementation.createHTMLDocument) {
1690+
assert.expect(0)
1691+
1692+
return
1693+
}
1694+
1695+
assert.expect(1)
1696+
1697+
var $trigger = $('<a href="#" rel="tooltip" data-sanitize="false" data-trigger="click" title="Another tooltip"/>')
1698+
.appendTo('#qunit-fixture')
1699+
.bootstrapTooltip({
1700+
template: [
1701+
'<span aria-pressed="true">Some content</span>'
1702+
].join('')
1703+
})
1704+
1705+
var tooltip = $trigger.data('bs.tooltip')
1706+
1707+
assert.strictEqual(tooltip.options.sanitize, true)
1708+
})
15291709
})

0 commit comments

Comments
 (0)