--- Begin Message ---
- To: Debian Bug Tracking System <submit@bugs.debian.org>
- Subject: stretch-pu: package twitter-bootstrap3/3.3.7+dfsg-2+deb9u1
- From: Xavier Guimard <yadd@debian.org>
- Date: Thu, 21 Feb 2019 21:50:00 +0100
- Message-id: <155078220073.26776.9572207327254728611.reportbug@madebian.lemonldap-ng.org>
Package: release.debian.org
Severity: normal
Tags: stretch
User: release.debian.org@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 <yadd@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 <yadd@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
--- End Message ---