CVE-2018-20677
Description
In Bootstrap before 3.4.0, XSS is possible in the affix configuration target property.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Cross-site scripting (XSS) vulnerability in Bootstrap's affix plugin allows attackers to inject arbitrary JavaScript via the target property before version 3.4.0.
Vulnerability
In Bootstrap versions prior to 3.4.0, the affix plugin does not properly sanitize the target configuration property, leading to a cross-site scripting (XSS) vulnerability. An attacker can inject arbitrary HTML and JavaScript through this property. [1]
Exploitation
An attacker must be able to control the value of the target property passed to the affix plugin, typically via user input or data from an untrusted source. By providing a malicious string containing JavaScript, the attacker can execute arbitrary code in the context of the victim's browser when the affix plugin processes the target. [1]
Impact
Successful exploitation allows the attacker to execute arbitrary JavaScript in the user's browser, potentially leading to session hijacking, data theft, or defacement. The attack runs in the context of the affected web page. [1]
Mitigation
Upgrade to Bootstrap version 3.4.0 or later, which fixes the issue. Red Hat also released an advisory (RHBA-2019:1076) for affected products. [1] No workaround is documented; the only mitigation is to update.
AI Insight generated on May 22, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
bootstrapnpm | < 3.4.0 | 3.4.0 |
bootstrap-sassnpm | < 3.4.0 | 3.4.0 |
twbs/bootstrapPackagist | < 3.4.0 | 3.4.0 |
org.webjars:bootstrapMaven | < 3.4.0 | 3.4.0 |
bootstrapRubyGems | < 3.4.0 | 3.4.0 |
bootstrap-sassRubyGems | < 3.4.0 | 3.4.0 |
bootstrapNuGet | < 3.4.0 | 3.4.0 |
Affected products
49- osv-coords48 versionspkg:apk/chainguard/grafana-10.4pkg:apk/chainguard/grafana-10.4-oci-compatpkg:apk/chainguard/grafana-11.2pkg:apk/chainguard/grafana-11.2-oci-compatpkg:apk/chainguard/grafana-11.3pkg:apk/chainguard/grafana-11.3-oci-compatpkg:apk/chainguard/grafana-11.4pkg:apk/chainguard/grafana-11.4-oci-compatpkg:apk/chainguard/grafana-11.5pkg:apk/chainguard/grafana-11.5-oci-compatpkg:apk/chainguard/grafana-11.6pkg:apk/chainguard/grafana-11.6-oci-compatpkg:apk/chainguard/grafana-fips-11.2pkg:apk/chainguard/grafana-fips-11.2-oci-compatpkg:apk/chainguard/grafana-fips-11.3pkg:apk/chainguard/grafana-fips-11.3-oci-compatpkg:apk/chainguard/grafana-fips-11.4pkg:apk/chainguard/grafana-fips-11.4-oci-compatpkg:apk/chainguard/grafana-fips-11.5pkg:apk/chainguard/grafana-fips-11.5-oci-compatpkg:apk/chainguard/grafana-fips-11.6pkg:apk/chainguard/grafana-fips-11.6-oci-compatpkg:apk/wolfi/grafana-10.4pkg:apk/wolfi/grafana-11.2pkg:apk/wolfi/grafana-11.2-oci-compatpkg:apk/wolfi/grafana-11.3pkg:apk/wolfi/grafana-11.3-oci-compatpkg:apk/wolfi/grafana-11.4pkg:apk/wolfi/grafana-11.4-oci-compatpkg:apk/wolfi/grafana-11.5pkg:apk/wolfi/grafana-11.5-oci-compatpkg:apk/wolfi/grafana-11.6pkg:apk/wolfi/grafana-11.6-oci-compatpkg:composer/twbs/bootstrappkg:gem/bootstrappkg:gem/bootstrap-sasspkg:maven/org.webjars/bootstrappkg:npm/bootstrappkg:npm/bootstrap-sasspkg:nuget/bootstrappkg:rpm/almalinux/custodiapkg:rpm/almalinux/python3-custodiapkg:rpm/almalinux/python3-jwcryptopkg:rpm/almalinux/python3-kdcproxypkg:rpm/almalinux/python3-pyusbpkg:rpm/almalinux/python3-qrcodepkg:rpm/almalinux/python3-qrcode-corepkg:rpm/almalinux/python3-yubico
< 10.4.19.01-r4+ 47 more
- (no CPE)range: < 10.4.19.01-r4
- (no CPE)range: < 10.4.19.01-r4
- (no CPE)range: < 11.2.10.01-r7
- (no CPE)range: < 11.2.10.01-r7
- (no CPE)range: < 11.3.9-r5
- (no CPE)range: < 11.3.9-r5
- (no CPE)range: < 11.4.8-r2
- (no CPE)range: < 11.4.8-r2
- (no CPE)range: < 11.5.10-r0
- (no CPE)range: < 11.5.10-r0
- (no CPE)range: < 11.6.7-r0
- (no CPE)range: < 11.6.7-r0
- (no CPE)range: < 11.2.10.01-r6
- (no CPE)range: < 11.2.10.01-r6
- (no CPE)range: < 11.3.9-r4
- (no CPE)range: < 11.3.9-r4
- (no CPE)range: < 11.4.8-r2
- (no CPE)range: < 11.4.8-r2
- (no CPE)range: < 11.5.10-r0
- (no CPE)range: < 11.5.10-r0
- (no CPE)range: < 11.6.7-r0
- (no CPE)range: < 11.6.7-r0
- (no CPE)range: < 10.4.19.01-r4
- (no CPE)range: < 11.2.10.01-r7
- (no CPE)range: < 11.2.10.01-r7
- (no CPE)range: < 11.3.9-r5
- (no CPE)range: < 11.3.9-r5
- (no CPE)range: < 11.4.8-r2
- (no CPE)range: < 11.4.8-r2
- (no CPE)range: < 11.5.10-r0
- (no CPE)range: < 11.5.10-r0
- (no CPE)range: < 11.6.7-r0
- (no CPE)range: < 11.6.7-r0
- (no CPE)range: < 3.4.0
- (no CPE)range: < 3.4.0
- (no CPE)range: < 3.4.0
- (no CPE)range: < 3.4.0
- (no CPE)range: < 3.4.0
- (no CPE)range: < 3.4.0
- (no CPE)range: < 3.4.0
- (no CPE)range: < 0.6.0-3.module_el8.6.0+2881+2f24dc92
- (no CPE)range: < 0.6.0-3.module_el8.6.0+2881+2f24dc92
- (no CPE)range: < 0.5.0-1.module_el8.5.0+2641+983b221b
- (no CPE)range: < 0.4-5.module_el8.6.0+2881+2f24dc92
- (no CPE)range: < 1.0.0-9.module_el8.5.0+2641+983b221b
- (no CPE)range: < 5.1-12.module_el8.6.0+2881+2f24dc92
- (no CPE)range: < 5.1-12.module_el8.6.0+2737+7e73ea90
- (no CPE)range: < 1.3.2-9.module_el8.5.0+2641+983b221b
Patches
12a5ba23ce8f0Fix/xss issues on data attributes (#27047)
6 files changed · +49 −4
js/affix.js+3 −1 modified@@ -16,7 +16,9 @@ var Affix = function (element, options) { this.options = $.extend({}, Affix.DEFAULTS, options) - this.$target = $(this.options.target) + var target = this.options.target === Affix.DEFAULTS.target ? $(this.options.target) : $(document).find(this.options.target) + + this.$target = target .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this)) .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
js/collapse.js+1 −1 modified@@ -137,7 +137,7 @@ } Collapse.prototype.getParent = function () { - return $(this.options.parent) + return $(document).find(this.options.parent) .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]') .each($.proxy(function (i, element) { var $element = $(element)
js/tests/unit/affix.js+15 −0 modified@@ -104,4 +104,19 @@ $(function () { }, 250) }, 250) }) + + QUnit.test('should raise exception to avoid xss on target', function (assert) { + assert.expect(1) + assert.throws(function () { + + var templateHTML = '<div id="affixTarget"></div>' + $(templateHTML).appendTo(document.body) + + $('#affixTarget').bootstrapAffix({ + target: '<img src=1 onerror=\'alert(0)\'>' + }) + + }, new Error('Syntax error, unrecognized expression: <img src=1 onerror=\'alert(0)\'>')) + }) + })
js/tests/unit/collapse.js+10 −0 modified@@ -440,4 +440,14 @@ $(function () { .bootstrapCollapse('show') }) + QUnit.test('should raise exception to avoid xss on data-parent', function (assert) { + assert.expect(1) + assert.throws(function () { + $('<a role="button" data-toggle="collapse" data-parent="<img src=1 onerror=\'alert(0)\'>" href="#collapseThree">') + .appendTo('#qunit-fixture') + .bootstrapCollapse('show') + .trigger('click'); + }, new Error('Syntax error, unrecognized expression: <img src=1 onerror=\'alert(0)\'>')) + }) + })
js/tests/unit/tooltip.js+18 −0 modified@@ -1322,4 +1322,22 @@ $(function () { }) }) + QUnit.test('should raise exception to avoid xss on data-container', function (assert) { + assert.expect(1) + assert.throws(function () { + $('<button data-toggle="tooltip" data-container="<img src=1 onerror=\'alert(0)\'>" title="Tooltip on right">Tooltip on right</button>') + .appendTo('#qunit-fixture') + .bootstrapTooltip('show') + }, new Error('Syntax error, unrecognized expression: <img src=1 onerror=\'alert(0)\'>')) + }) + + QUnit.test('should raise exception to avoid xss on data-viewport', function (assert) { + assert.expect(1) + assert.throws(function () { + $('<button data-toggle="tooltip" data-viewport="<img src=1 onerror=\'alert(0)\'>" title="Tooltip on right">Tooltip on right</button>') + .appendTo('#qunit-fixture') + .bootstrapTooltip('show') + }, new Error('Syntax error, unrecognized expression: <img src=1 onerror=\'alert(0)\'>')) + }) + })
js/tooltip.js+2 −2 modified@@ -51,7 +51,7 @@ this.type = type this.$element = $(element) this.options = this.getOptions(options) - this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport)) + this.$viewport = this.options.viewport && $(document).find($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport)) this.inState = { click: false, hover: false, focus: false } if (this.$element[0] instanceof document.constructor && !this.options.selector) { @@ -204,7 +204,7 @@ .addClass(placement) .data('bs.' + this.type, this) - this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) + this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element) this.$element.trigger('inserted.bs.' + this.type) var pos = this.getPosition()
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
22- access.redhat.com/errata/RHBA-2019:1076ghsavendor-advisoryx_refsource_REDHATWEB
- access.redhat.com/errata/RHBA-2019:1570ghsavendor-advisoryx_refsource_REDHATWEB
- access.redhat.com/errata/RHSA-2019:1456ghsavendor-advisoryx_refsource_REDHATWEB
- access.redhat.com/errata/RHSA-2019:3023ghsavendor-advisoryx_refsource_REDHATWEB
- access.redhat.com/errata/RHSA-2020:0132ghsavendor-advisoryx_refsource_REDHATWEB
- access.redhat.com/errata/RHSA-2020:0133ghsavendor-advisoryx_refsource_REDHATWEB
- github.com/advisories/GHSA-ph58-4vrj-w6hrghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2018-20677ghsaADVISORY
- blog.getbootstrap.com/2018/12/13/bootstrap-3-4-0ghsaWEB
- blog.getbootstrap.com/2018/12/13/bootstrap-3-4-0/mitrex_refsource_MISC
- github.com/rubysec/ruby-advisory-db/blob/master/gems/bootstrap-sass/CVE-2018-20677.ymlghsaWEB
- github.com/rubysec/ruby-advisory-db/blob/master/gems/bootstrap/CVE-2018-20677.ymlghsaWEB
- github.com/twbs/bootstrap/commit/2a5ba23ce8f041f3548317acc992ed8a736b609dghsaWEB
- github.com/twbs/bootstrap/issues/27045ghsax_refsource_MISCWEB
- github.com/twbs/bootstrap/issues/27915ghsax_refsource_MISCWEB
- github.com/twbs/bootstrap/issues/27915ghsax_refsource_MISCWEB
- github.com/twbs/bootstrap/pull/27047ghsax_refsource_MISCWEB
- lists.apache.org/thread.html/52e0e6b5df827ee7f1e68f7cc3babe61af3b2160f5d74a85469b7b0e%40%3Cdev.superset.apache.org%3Emitremailing-listx_refsource_MLIST
- lists.apache.org/thread.html/52e0e6b5df827ee7f1e68f7cc3babe61af3b2160f5d74a85469b7b0e@%3Cdev.superset.apache.org%3EghsaWEB
- lists.apache.org/thread.html/rd0e44e8ef71eeaaa3cf3d1b8b41eb25894372e2995ec908ce7624d26%40%3Ccommits.pulsar.apache.org%3Emitremailing-listx_refsource_MLIST
- lists.apache.org/thread.html/rd0e44e8ef71eeaaa3cf3d1b8b41eb25894372e2995ec908ce7624d26@%3Ccommits.pulsar.apache.org%3EghsaWEB
- www.tenable.com/security/tns-2021-14mitrex_refsource_CONFIRM
News mentions
0No linked articles in our index yet.