diff options
author | Patrick H. Lauke <redux@splintered.co.uk> | 2020-06-19 11:31:37 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-19 11:31:37 +0300 |
commit | edbcc401c28e539ecdcf3c49c7ef2a74d0c28ebd (patch) | |
tree | a1e408cd3c48309c49fc06d7dbb52d96ae02fae0 | |
parent | 7acf586d3efa9b2bad6a93d81c7cdc3560de6cdf (diff) |
Change whitelist to allowlist (#31066)
Co-authored-by: XhmikosR <xhmikosr@gmail.com>
Co-authored-by: Mark Otto <markd.otto@gmail.com>
-rw-r--r-- | build/change-version.js | 2 | ||||
-rw-r--r-- | js/src/tooltip.js | 12 | ||||
-rw-r--r-- | js/src/util/sanitizer.js | 12 | ||||
-rw-r--r-- | js/tests/unit/util/sanitizer.spec.js | 14 | ||||
-rw-r--r-- | site/content/docs/5.0/components/popovers.md | 6 | ||||
-rw-r--r-- | site/content/docs/5.0/components/tooltips.md | 4 | ||||
-rw-r--r-- | site/content/docs/5.0/getting-started/javascript.md | 14 | ||||
-rw-r--r-- | site/content/docs/5.0/migration.md | 2 |
8 files changed, 34 insertions, 32 deletions
diff --git a/build/change-version.js b/build/change-version.js index ba6e46a471..b8a640fa8e 100644 --- a/build/change-version.js +++ b/build/change-version.js @@ -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', diff --git a/js/src/tooltip.js b/js/src/tooltip.js index 64011796de..33c0f6eec2 100644 --- a/js/src/tooltip.js +++ b/js/src/tooltip.js @@ -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 diff --git a/js/src/util/sanitizer.js b/js/src/util/sanitizer.js index e1ec36a400..27bdf6cb1f 100644 --- a/js/src/util/sanitizer.js +++ b/js/src/util/sanitizer.js @@ -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) } }) diff --git a/js/tests/unit/util/sanitizer.spec.js b/js/tests/unit/util/sanitizer.spec.js index c4259e7fd6..dcfad8436f 100644 --- a/js/tests/unit/util/sanitizer.spec.js +++ b/js/tests/unit/util/sanitizer.spec.js @@ -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() diff --git a/site/content/docs/5.0/components/popovers.md b/site/content/docs/5.0/components/popovers.md index 4e42ee0727..73be8ad10b 100644 --- a/site/content/docs/5.0/components/popovers.md +++ b/site/content/docs/5.0/components/popovers.md @@ -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> diff --git a/site/content/docs/5.0/components/tooltips.md b/site/content/docs/5.0/components/tooltips.md index 19d95e0281..385ec99f00 100644 --- a/site/content/docs/5.0/components/tooltips.md +++ b/site/content/docs/5.0/components/tooltips.md @@ -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> diff --git a/site/content/docs/5.0/getting-started/javascript.md b/site/content/docs/5.0/getting-started/javascript.md index 3c5eecf360..38b2266234 100644 --- a/site/content/docs/5.0/getting-started/javascript.md +++ b/site/content/docs/5.0/getting-started/javascript.md @@ -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: diff --git a/site/content/docs/5.0/migration.md b/site/content/docs/5.0/migration.md index a4df01fe3c..a366abb933 100644 --- a/site/content/docs/5.0/migration.md +++ b/site/content/docs/5.0/migration.md @@ -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 |