Package: release.debian.org Severity: normal Tags: stretch User: release.debian....@packages.debian.org Usertags: pu
Hi all, A little fix for CVE-2019-8331. Cheers, Xavier -- System Information: Debian Release: buster/sid APT prefers testing APT policy: (900, 'testing'), (500, 'unstable') Architecture: amd64 (x86_64) Foreign Architectures: i386 Kernel: Linux 4.19.0-2-amd64 (SMP w/4 CPU cores) Locale: LANG=fr_FR.UTF-8, LC_CTYPE=fr_FR.UTF-8 (charmap=UTF-8), LANGUAGE= (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Init: systemd (via /run/systemd/system) LSM: AppArmor: enabled
diff -Nru twitter-bootstrap3-3.3.7+dfsg/debian/changelog twitter-bootstrap3-3.3.7+dfsg/debian/changelog --- twitter-bootstrap3-3.3.7+dfsg/debian/changelog 2019-02-04 22:25:25.000000000 +0100 +++ twitter-bootstrap3-3.3.7+dfsg/debian/changelog 2019-02-21 21:42:06.000000000 +0100 @@ -1,3 +1,9 @@ +twitter-bootstrap3 (3.3.7+dfsg-2+deb9u2) UNRELEASED; urgency=medium + + * Add patch to fix CVE-2019-8331: XSS in tooltip or popover + + -- Xavier Guimard <y...@debian.org> Thu, 21 Feb 2019 21:42:06 +0100 + twitter-bootstrap3 (3.3.7+dfsg-2+deb9u1) stretch; urgency=high * Team upload. diff -Nru twitter-bootstrap3-3.3.7+dfsg/debian/patches/CVE-2019-8331.patch twitter-bootstrap3-3.3.7+dfsg/debian/patches/CVE-2019-8331.patch --- twitter-bootstrap3-3.3.7+dfsg/debian/patches/CVE-2019-8331.patch 1970-01-01 01:00:00.000000000 +0100 +++ twitter-bootstrap3-3.3.7+dfsg/debian/patches/CVE-2019-8331.patch 2019-02-21 21:40:12.000000000 +0100 @@ -0,0 +1,257 @@ +Description: Fix XSS - CVE-2019-8331 +Author: Xavier Guimard <y...@debian.org> +Origin: upstream +Forwarded: not-needed +Last-Update: 2019-02-21 + +--- a/js/dropdown.js ++++ b/js/dropdown.js +@@ -29,7 +29,7 @@ + selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 + } + +- var $parent = selector && $(document).find(selector) ++ var $parent = selector !== '#' ? $(document).find(selector) : null + + return $parent && $parent.length ? $parent : $this.parent() + } +--- a/js/popover.js ++++ b/js/popover.js +@@ -45,10 +45,25 @@ + var title = this.getTitle() + var content = this.getContent() + +- $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title) +- $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events +- this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text' +- ](content) ++ if (this.options.html) { ++ var typeContent = typeof content ++ ++ if (this.options.sanitize) { ++ title = this.sanitizeHtml(title) ++ ++ if (typeContent === 'string') { ++ content = this.sanitizeHtml(content) ++ } ++ } ++ ++ $tip.find('.popover-title').html(title) ++ $tip.find('.popover-content').children().detach().end()[ ++ typeContent === 'string' ? 'html' : 'append' ++ ](content) ++ } else { ++ $tip.find('.popover-title').text(title) ++ $tip.find('.popover-content').children().detach().end().text(content) ++ } + + $tip.removeClass('fade top bottom left right in') + +--- a/js/tooltip.js ++++ b/js/tooltip.js +@@ -11,6 +11,137 @@ + +function ($) { + 'use strict'; + ++ var DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn'] ++ ++ var uriAttrs = [ ++ 'background', ++ 'cite', ++ 'href', ++ 'itemtype', ++ 'longdesc', ++ 'poster', ++ 'src', ++ 'xlink:href' ++ ] ++ ++ var ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i ++ ++ var DefaultWhitelist = { ++ // Global attributes allowed on any supplied element below. ++ '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN], ++ a: ['target', 'href', 'title', 'rel'], ++ area: [], ++ b: [], ++ br: [], ++ col: [], ++ code: [], ++ div: [], ++ em: [], ++ hr: [], ++ h1: [], ++ h2: [], ++ h3: [], ++ h4: [], ++ h5: [], ++ h6: [], ++ i: [], ++ img: ['src', 'alt', 'title', 'width', 'height'], ++ li: [], ++ ol: [], ++ p: [], ++ pre: [], ++ s: [], ++ small: [], ++ span: [], ++ sub: [], ++ sup: [], ++ strong: [], ++ u: [], ++ ul: [] ++ } ++ ++ /** ++ * A pattern that recognizes a commonly useful subset of URLs that are safe. ++ * ++ * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts ++ */ ++ var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi ++ ++ /** ++ * A pattern that matches safe data URLs. Only matches image, video and audio types. ++ * ++ * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts ++ */ ++ var DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i ++ ++ function allowedAttribute(attr, allowedAttributeList) { ++ var attrName = attr.nodeName.toLowerCase() ++ ++ if ($.inArray(attrName, allowedAttributeList) !== -1) { ++ if ($.inArray(attrName, uriAttrs) !== -1) { ++ return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN)) ++ } ++ ++ return true ++ } ++ ++ var regExp = $(allowedAttributeList).filter(function (index, value) { ++ return value instanceof RegExp ++ }) ++ ++ // Check if a regular expression validates the attribute. ++ for (var i = 0, l = regExp.length; i < l; i++) { ++ if (attrName.match(regExp[i])) { ++ return true ++ } ++ } ++ ++ return false ++ } ++ ++ function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) { ++ if (unsafeHtml.length === 0) { ++ return unsafeHtml ++ } ++ ++ if (sanitizeFn && typeof sanitizeFn === 'function') { ++ return sanitizeFn(unsafeHtml) ++ } ++ ++ // IE 8 and below don't support createHTMLDocument ++ if (!document.implementation || !document.implementation.createHTMLDocument) { ++ return unsafeHtml ++ } ++ ++ var createdDocument = document.implementation.createHTMLDocument('sanitization') ++ createdDocument.body.innerHTML = unsafeHtml ++ ++ var whitelistKeys = $.map(whiteList, function (el, i) { return i }) ++ var elements = $(createdDocument.body).find('*') ++ ++ for (var i = 0, len = elements.length; i < len; i++) { ++ var el = elements[i] ++ var elName = el.nodeName.toLowerCase() ++ ++ if ($.inArray(elName, whitelistKeys) === -1) { ++ el.parentNode.removeChild(el) ++ ++ continue ++ } ++ ++ var attributeList = $.map(el.attributes, function (el) { return el }) ++ var whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || []) ++ ++ for (var j = 0, len2 = attributeList.length; j < len2; j++) { ++ if (!allowedAttribute(attributeList[j], whitelistedAttributes)) { ++ el.removeAttribute(attributeList[j].nodeName) ++ } ++ } ++ } ++ ++ return createdDocument.body.innerHTML ++ } ++ + // TOOLTIP PUBLIC CLASS DEFINITION + // =============================== + +@@ -43,7 +174,10 @@ + viewport: { + selector: 'body', + padding: 0 +- } ++ }, ++ sanitize : true, ++ sanitizeFn : null, ++ whiteList : DefaultWhitelist + } + + Tooltip.prototype.init = function (type, element, options) { +@@ -84,7 +218,15 @@ + } + + Tooltip.prototype.getOptions = function (options) { +- options = $.extend({}, this.getDefaults(), this.$element.data(), options) ++ var dataAttributes = this.$element.data() ++ ++ for (var dataAttr in dataAttributes) { ++ if (dataAttributes.hasOwnProperty(dataAttr) && $.inArray(dataAttr, DISALLOWED_ATTRIBUTES) !== -1) { ++ delete dataAttributes[dataAttr] ++ } ++ } ++ ++ options = $.extend({}, this.getDefaults(), dataAttributes, options) + + if (options.delay && typeof options.delay == 'number') { + options.delay = { +@@ -93,6 +235,10 @@ + } + } + ++ if (options.sanitize) { ++ options.template = sanitizeHtml(options.template, options.whiteList, options.sanitizeFn) ++ } ++ + return options + } + +@@ -306,7 +452,16 @@ + var $tip = this.tip() + var title = this.getTitle() + +- $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) ++ if (this.options.html) { ++ if (this.options.sanitize) { ++ title = sanitizeHtml(title, this.options.whiteList, this.options.sanitizeFn) ++ } ++ ++ $tip.find('.tooltip-inner').html(title) ++ } else { ++ $tip.find('.tooltip-inner').text(title) ++ } ++ + $tip.removeClass('fade in top bottom left right') + } + +@@ -487,6 +642,9 @@ + }) + } + ++ Tooltip.prototype.sanitizeHtml = function (unsafeHtml) { ++ return sanitizeHtml(unsafeHtml, this.options.whiteList, this.options.sanitizeFn) ++ } + + // TOOLTIP PLUGIN DEFINITION + // ========================= diff -Nru twitter-bootstrap3-3.3.7+dfsg/debian/patches/series twitter-bootstrap3-3.3.7+dfsg/debian/patches/series --- twitter-bootstrap3-3.3.7+dfsg/debian/patches/series 2019-02-04 22:25:25.000000000 +0100 +++ twitter-bootstrap3-3.3.7+dfsg/debian/patches/series 2019-02-21 21:41:25.000000000 +0100 @@ -1 +1,2 @@ fix-xss-vulnerabilities.patch +CVE-2019-8331.patch