diff --git a/website/static/vendor/bootstrap/js/bootstrap.js b/website/static/vendor/bootstrap/js/bootstrap.js index 721ca5986..d533c679f 100644 --- a/website/static/vendor/bootstrap/js/bootstrap.js +++ b/website/static/vendor/bootstrap/js/bootstrap.js @@ -1328,7 +1328,7 @@ function sanitizeInput(input) { 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 && $(sanitizeSelector($.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) { @@ -2028,7 +2028,7 @@ function sanitizeInput(input) { '[data-target="' + target + '"],' + this.selector + '[href="' + target + '"]' - var active = $(selector) + var active = $(escapePotentialXSS(selector)) .parents('li') .addClass('active') @@ -2042,7 +2042,7 @@ function sanitizeInput(input) { } ScrollSpy.prototype.clear = function () { - $(this.selector) + $(escapePotentialXSS(this.selector)) .parentsUntil(this.options.target, '.active') .removeClass('active') } @@ -2407,3 +2407,20 @@ function sanitizeInput(input) { }) }(jQuery); +function escapePotentialXSS(selector) { + // Escaping only the specific characters that can lead to XSS + // such as <, >, ", ', and ` which are not valid in CSS selectors + // and can be used for XSS if injected into HTML content. + return selector.replace(/[<>\"'`]/g, function(match) { + // Convert potentially dangerous characters to their + // corresponding HTML entity representations. + switch(match) { + case '<': return '<'; + case '>': return '>'; + case '"': return '"'; + case '\'': return '''; + case '`': return '`'; + default: return match; + } + }); +}