]> git.ipfire.org Git - thirdparty/bootstrap.git/commitdiff
Change whitelist to allowlist (#31066)
authorPatrick H. Lauke <redux@splintered.co.uk>
Fri, 19 Jun 2020 08:31:37 +0000 (09:31 +0100)
committerGitHub <noreply@github.com>
Fri, 19 Jun 2020 08:31:37 +0000 (11:31 +0300)
Co-authored-by: XhmikosR <xhmikosr@gmail.com>
Co-authored-by: Mark Otto <markd.otto@gmail.com>
build/change-version.js
js/src/tooltip.js
js/src/util/sanitizer.js
js/tests/unit/util/sanitizer.spec.js
site/content/docs/5.0/components/popovers.md
site/content/docs/5.0/components/tooltips.md
site/content/docs/5.0/getting-started/javascript.md
site/content/docs/5.0/migration.md

index ba6e46a47184cec201c74484579fa4e02184bdd2..b8a640fa8ee312e407bc6755e794252605d71aba 100644 (file)
@@ -95,7 +95,7 @@ function main(args) {
     'vendor'
   ])
   const INCLUDED_EXTENSIONS = new Set([
-    // This extension whitelist is how we avoid modifying binary files
+    // This extension allowlist is how we avoid modifying binary files
     '',
     '.css',
     '.html',
index 64011796de39c5ad883d30b2a9c10ea860aff211..33c0f6eec22441868a9192e40e1e1bd0170fb171 100644 (file)
@@ -17,7 +17,7 @@ import {
   typeCheckConfig
 } from './util/index'
 import {
-  DefaultWhitelist,
+  DefaultAllowlist,
   sanitizeHtml
 } from './util/sanitizer'
 import Data from './dom/data'
@@ -38,7 +38,7 @@ const DATA_KEY = 'bs.tooltip'
 const EVENT_KEY = `.${DATA_KEY}`
 const CLASS_PREFIX = 'bs-tooltip'
 const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\s)${CLASS_PREFIX}\\S+`, 'g')
-const DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn']
+const DISALLOWED_ATTRIBUTES = ['sanitize', 'allowList', 'sanitizeFn']
 
 const DefaultType = {
   animation: 'boolean',
@@ -55,7 +55,7 @@ const DefaultType = {
   boundary: '(string|element)',
   sanitize: 'boolean',
   sanitizeFn: '(null|function)',
-  whiteList: 'object',
+  allowList: 'object',
   popperConfig: '(null|object)'
 }
 
@@ -84,7 +84,7 @@ const Default = {
   boundary: 'scrollParent',
   sanitize: true,
   sanitizeFn: null,
-  whiteList: DefaultWhitelist,
+  allowList: DefaultAllowlist,
   popperConfig: null
 }
 
@@ -428,7 +428,7 @@ class Tooltip {
 
     if (this.config.html) {
       if (this.config.sanitize) {
-        content = sanitizeHtml(content, this.config.whiteList, this.config.sanitizeFn)
+        content = sanitizeHtml(content, this.config.allowList, this.config.sanitizeFn)
       }
 
       element.innerHTML = content
@@ -711,7 +711,7 @@ class Tooltip {
     typeCheckConfig(NAME, config, this.constructor.DefaultType)
 
     if (config.sanitize) {
-      config.template = sanitizeHtml(config.template, config.whiteList, config.sanitizeFn)
+      config.template = sanitizeHtml(config.template, config.allowList, config.sanitizeFn)
     }
 
     return config
index e1ec36a400510ecd8492497ee8e5549b1e0570d4..27bdf6cb1ffdca6fdecab710677949624318ddf1 100644 (file)
@@ -55,7 +55,7 @@ const allowedAttribute = (attr, allowedAttributeList) => {
   return false
 }
 
-export const DefaultWhitelist = {
+export const DefaultAllowlist = {
   // Global attributes allowed on any supplied element below.
   '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],
   a: ['target', 'href', 'title', 'rel'],
@@ -89,7 +89,7 @@ export const DefaultWhitelist = {
   ul: []
 }
 
-export function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) {
+export function sanitizeHtml(unsafeHtml, allowList, sanitizeFn) {
   if (!unsafeHtml.length) {
     return unsafeHtml
   }
@@ -100,24 +100,24 @@ export function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) {
 
   const domParser = new window.DOMParser()
   const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html')
-  const whitelistKeys = Object.keys(whiteList)
+  const allowlistKeys = Object.keys(allowList)
   const elements = [].concat(...createdDocument.body.querySelectorAll('*'))
 
   for (let i = 0, len = elements.length; i < len; i++) {
     const el = elements[i]
     const elName = el.nodeName.toLowerCase()
 
-    if (whitelistKeys.indexOf(elName) === -1) {
+    if (allowlistKeys.indexOf(elName) === -1) {
       el.parentNode.removeChild(el)
 
       continue
     }
 
     const attributeList = [].concat(...el.attributes)
-    const whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || [])
+    const allowedAttributes = [].concat(allowList['*'] || [], allowList[elName] || [])
 
     attributeList.forEach(attr => {
-      if (!allowedAttribute(attr, whitelistedAttributes)) {
+      if (!allowedAttribute(attr, allowedAttributes)) {
         el.removeAttribute(attr.nodeName)
       }
     })
index c4259e7fd66cb4ef4d4098b0591e0c3574eaaf25..dcfad8436f8fef0337b2698242b99c1558dc8be8 100644 (file)
@@ -1,11 +1,11 @@
-import { DefaultWhitelist, sanitizeHtml } from '../../../src/util/sanitizer'
+import { DefaultAllowlist, sanitizeHtml } from '../../../src/util/sanitizer'
 
 describe('Sanitizer', () => {
   describe('sanitizeHtml', () => {
     it('should return the same on empty string', () => {
       const empty = ''
 
-      const result = sanitizeHtml(empty, DefaultWhitelist, null)
+      const result = sanitizeHtml(empty, DefaultAllowlist, null)
 
       expect(result).toEqual(empty)
     })
@@ -18,7 +18,7 @@ describe('Sanitizer', () => {
         '</div>'
       ].join('')
 
-      const result = sanitizeHtml(template, DefaultWhitelist, null)
+      const result = sanitizeHtml(template, DefaultAllowlist, null)
 
       expect(result.indexOf('script') === -1).toEqual(true)
     })
@@ -30,20 +30,20 @@ describe('Sanitizer', () => {
         '</div>'
       ].join('')
 
-      const result = sanitizeHtml(template, DefaultWhitelist, null)
+      const result = sanitizeHtml(template, DefaultAllowlist, null)
 
       expect(result.indexOf('aria-pressed') !== -1).toEqual(true)
       expect(result.indexOf('class="test"') !== -1).toEqual(true)
     })
 
-    it('should remove not whitelist tags', () => {
+    it('should remove tags not in allowlist', () => {
       const template = [
         '<div>',
         '  <script>alert(7)</script>',
         '</div>'
       ].join('')
 
-      const result = sanitizeHtml(template, DefaultWhitelist, null)
+      const result = sanitizeHtml(template, DefaultAllowlist, null)
 
       expect(result.indexOf('<script>') === -1).toEqual(true)
     })
@@ -61,7 +61,7 @@ describe('Sanitizer', () => {
 
       spyOn(DOMParser.prototype, 'parseFromString')
 
-      const result = sanitizeHtml(template, DefaultWhitelist, mySanitize)
+      const result = sanitizeHtml(template, DefaultAllowlist, mySanitize)
 
       expect(result).toEqual(template)
       expect(DOMParser.prototype.parseFromString).not.toHaveBeenCalled()
index 4e42ee07277b06ba5b98217c4ac716b99cb7cd7e..73be8ad10bfb1443920fea322f6ab5a28f830609 100644 (file)
@@ -142,7 +142,7 @@ To allow keyboard users to activate your popovers, you should only add them to H
 
 While you can insert rich, structured HTML in popovers with the `html` option, we strongly recommend that you avoid adding an excessive amount of content. The way popovers currently work is that, once displayed, their content is tied to the trigger element with the `aria-describedby` attribute. As a result, the entirety of the popover's content will be announced to assistive technology users as one long, uninterrupted stream.
 
-Additionally, while it is possible to also include interactive controls (such as form elements or links) in your popover (by adding these elements to the `whiteList` or allowed attributes and tags), be aware that currently the popover does not manage keyboard focus order. When a keyboard user opens a popover, focus remains on the triggering element, and as the popover usually does not immediately follow the trigger in the document's structure, there is no guarantee that moving forward/pressing <kbd>TAB</kbd> will move a keyboard user into the popover itself. In short, simply adding interactive controls to a popover is likely to make these controls unreachable/unusable for keyboard users and users of assistive technologies, or at the very least make for an illogical overall focus order. In these cases, consider using a modal dialog instead.
+Additionally, while it is possible to also include interactive controls (such as form elements or links) in your popover (by adding these elements to the `allowList` of allowed attributes and tags), be aware that currently the popover does not manage keyboard focus order. When a keyboard user opens a popover, focus remains on the triggering element, and as the popover usually does not immediately follow the trigger in the document's structure, there is no guarantee that moving forward/pressing <kbd>TAB</kbd> will move a keyboard user into the popover itself. In short, simply adding interactive controls to a popover is likely to make these controls unreachable/unusable for keyboard users and users of assistive technologies, or at the very least make for an illogical overall focus order. In these cases, consider using a modal dialog instead.
 {{< /callout >}}
 
 ### Options
@@ -150,7 +150,7 @@ Additionally, while it is possible to also include interactive controls (such as
 Options can be passed via data attributes or JavaScript. For data attributes, append the option name to `data-`, as in `data-animation=""`.
 
 {{< callout warning >}}
-Note that for security reasons the `sanitize`, `sanitizeFn` and `whiteList` options cannot be supplied using data attributes.
+Note that for security reasons the `sanitize`, `sanitizeFn`, and `allowList` options cannot be supplied using data attributes.
 {{< /callout >}}
 
 <table class="table">
@@ -270,7 +270,7 @@ Note that for security reasons the `sanitize`, `sanitizeFn` and `whiteList` opti
       <td>Enable or disable the sanitization. If activated <code>'template'</code>, <code>'content'</code> and <code>'title'</code> options will be sanitized.</td>
     </tr>
     <tr>
-      <td>whiteList</td>
+      <td>allowList</td>
       <td>object</td>
       <td><a href="{{< docsref "/getting-started/javascript#sanitizer" >}}">Default value</a></td>
       <td>Object which contains allowed attributes and tags</td>
index 19d95e0281d77c17e1ae06a6515ae719dc018fc0..385ec99f006bd3b2c2669e8a739242174e8225db 100644 (file)
@@ -156,7 +156,7 @@ Elements with the `disabled` attribute aren't interactive, meaning users cannot
 Options can be passed via data attributes or JavaScript. For data attributes, append the option name to `data-`, as in `data-animation=""`.
 
 {{< callout warning >}}
-Note that for security reasons the `sanitize`, `sanitizeFn` and `whiteList` options cannot be supplied using data attributes.
+Note that for security reasons the `sanitize`, `sanitizeFn`, and `allowList` options cannot be supplied using data attributes.
 {{< /callout >}}
 
 <table class="table">
@@ -278,7 +278,7 @@ Note that for security reasons the `sanitize`, `sanitizeFn` and `whiteList` opti
       <td>Enable or disable the sanitization. If activated <code>'template'</code> and <code>'title'</code> options will be sanitized.</td>
     </tr>
     <tr>
-      <td>whiteList</td>
+      <td>allowList</td>
       <td>object</td>
       <td><a href="{{< docsref "/getting-started/javascript#sanitizer" >}}">Default value</a></td>
       <td>Object which contains allowed attributes and tags</td>
index 3c5eecf360e0a6bf02f5321a3d4a729d509657ee..38b2266234cf3aa55e250b5388303a280224274d 100644 (file)
@@ -161,11 +161,11 @@ Bootstrap's plugins don't fall back particularly gracefully when JavaScript is d
 
 Tooltips and Popovers use our built-in sanitizer to sanitize options which accept HTML.
 
-The default `whiteList` value is the following:
+The default `allowList` value is the following:
 
 {{< highlight js >}}
 var ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i
-var DefaultWhitelist = {
+var DefaultAllowlist = {
   // Global attributes allowed on any supplied element below.
   '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],
   a: ['target', 'href', 'title', 'rel'],
@@ -200,21 +200,21 @@ var DefaultWhitelist = {
 }
 {{< /highlight >}}
 
-If you want to add new values to this default `whiteList` you can do the following:
+If you want to add new values to this default `allowList` you can do the following:
 
 {{< highlight js >}}
-var myDefaultWhiteList = bootstrap.Tooltip.Default.whiteList
+var myDefaultAllowList = bootstrap.Tooltip.Default.allowList
 
 // To allow table elements
-myDefaultWhiteList.table = []
+myDefaultAllowList.table = []
 
 // To allow td elements and data-option attributes on td elements
-myDefaultWhiteList.td = ['data-option']
+myDefaultAllowList.td = ['data-option']
 
 // You can push your custom regex to validate your attributes.
 // Be careful about your regular expressions being too lax
 var myCustomRegex = /^data-my-app-[\w-]+/
-myDefaultWhiteList['*'].push(myCustomRegex)
+myDefaultAllowList['*'].push(myCustomRegex)
 {{< /highlight >}}
 
 If you want to bypass our sanitizer because you prefer to use a dedicated library, for example [DOMPurify](https://www.npmjs.com/package/dompurify), you should do the following:
index a4df01fe3c7cef252bc4f0ebd7dd265b4abd4370..a366abb933c58eed19f5fead70ba99dc5a848467 100644 (file)
@@ -172,10 +172,12 @@ Badges were overhauled to better differentiate themselves from buttons and to be
 ### Popovers
 
 - Renamed `.arrow` to `.popover-arrow`
+- Renamed `whiteList` option to `allowList`
 
 ### Tooltips
 
 - Renamed `.arrow` to `.tooltip-arrow`
+- Renamed `whiteList` option to `allowList`
 
 ## Accessibility