Skip to content

Commit 33eed6a

Browse files
committed
feat(RangeSlider): add sanitizer for tooltip content
1 parent c4b681d commit 33eed6a

File tree

2 files changed

+23
-1
lines changed

2 files changed

+23
-1
lines changed

docs/content/forms/range-slider.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,10 +194,14 @@ const rangeSlider = new RangeSlider(rangeSliderElement, {
194194
{{< partial "js-data-attributes.md" >}}
195195
{{< /markdown >}}
196196

197+
{{< callout warning >}}
198+
Please note that for security reasons, the `sanitize`, `sanitizeFn`, and `allowList` options cannot be supplied via data attributes.
199+
{{< /callout >}}
197200

198201
{{< bs-table >}}
199202
| Name | Type | Default | Description |
200203
| --- | --- | --- | --- |
204+
| `allowList` | object | [Default value](/getting-started/javascript#sanitizer) | Defines the set of permitted HTML tags and attributes that can safely appear in the tooltip content when HTML content is passedd. This helps maintain control over the output and prevent injection of malicious code. |
201205
| `clickableLabels` | boolean | `true` | Enables or disables the ability to click on labels to set slider values. |
202206
| `disabled` | boolean | `false` | Disables the slider, making it non-interactive and grayed out. |
203207
| `distance` | number | `0` | Sets the minimum distance between multiple slider handles. |
@@ -211,6 +215,8 @@ const rangeSlider = new RangeSlider(rangeSliderElement, {
211215
| `track` | boolean, 'fill' | `'fill'` | Controls the visual representation of the slider's track. When set to `'fill'`, the track is dynamically filled based on the slider's value(s). Setting it to `false` disables the filled track. |
212216
| `value` | array, number | `0` | Sets the initial value(s) of the slider. |
213217
| `vertical` | boolean | `false` | Rotates the slider to a vertical orientation. |
218+
| `sanitize` | boolean | `true` | Controls whether HTML content in the tooltip should be sanitized before rendering. Strongly recommended to leave enabled unless you’re fully managing the content and trust its source. |
219+
| `sanitizeFn` | null, function | `null` | You can define your own custom sanitization logic by passing a function here. Ideal if you want to use a specialized HTML sanitizer or integrate with existing security tool. |
214220
{{< /bs-table >}}
215221

216222

js/src/range-slider.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import EventHandler from './dom/event-handler.js'
1010
import Manipulator from './dom/manipulator.js'
1111
import SelectorEngine from './dom/selector-engine.js'
1212
import { defineJQueryPlugin, isRTL } from './util/index.js'
13+
import { DefaultAllowlist, sanitizeHtml } from './util/sanitizer.js'
1314

1415
/**
1516
* Constants
@@ -19,6 +20,7 @@ const NAME = 'range-slider'
1920
const DATA_KEY = 'coreui.range-slider'
2021
const EVENT_KEY = `.${DATA_KEY}`
2122
const DATA_API_KEY = '.data-api'
23+
const DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn'])
2224

2325
const EVENT_CHANGE = `change${EVENT_KEY}`
2426
const EVENT_INPUT = `input${EVENT_KEY}`
@@ -48,13 +50,16 @@ const SELECTOR_RANGE_SLIDER_LABEL = '.range-slider-label'
4850
const SELECTOR_RANGE_SLIDER_LABELS_CONTAINER = '.range-slider-labels-container'
4951

5052
const Default = {
53+
allowList: DefaultAllowlist,
5154
clickableLabels: true,
5255
disabled: false,
5356
distance: 0,
5457
labels: false,
5558
max: 100,
5659
min: 0,
5760
name: null,
61+
sanitize: true,
62+
sanitizeFn: null,
5863
step: 1,
5964
tooltips: true,
6065
tooltipsFormat: null,
@@ -64,13 +69,16 @@ const Default = {
6469
}
6570

6671
const DefaultType = {
72+
allowList: 'object',
6773
clickableLabels: 'boolean',
6874
disabled: 'boolean',
6975
distance: 'number',
7076
labels: '(array|boolean|string)',
7177
max: 'number',
7278
min: 'number',
7379
name: '(array|string|null)',
80+
sanitize: 'boolean',
81+
sanitizeFn: '(null|function)',
7482
step: '(number|string)',
7583
tooltips: 'boolean',
7684
tooltipsFormat: '(function|null)',
@@ -339,7 +347,9 @@ class RangeSlider extends BaseComponent {
339347
const tooltipInnerElement = this._createElement('div', CLASS_NAME_RANGE_SLIDER_TOOLTIP_INNER)
340348
const tooltipArrowElement = this._createElement('div', CLASS_NAME_RANGE_SLIDER_TOOLTIP_ARROW)
341349

342-
tooltipInnerElement.innerHTML = this._config.tooltipsFormat ? this._config.tooltipsFormat(input.value) : input.value
350+
tooltipInnerElement.innerHTML = this._config.tooltipsFormat ?
351+
(this._config.sanitize ? sanitizeHtml(this._config.tooltipsFormat(input.value), this._config.allowList, this._config.sanitizeFn) : this._config.tooltipsFormat(input.value)) :
352+
input.value
343353
tooltipElement.append(tooltipInnerElement, tooltipArrowElement)
344354

345355
input.parentNode.insertBefore(tooltipElement, input.nextSibling)
@@ -592,6 +602,12 @@ class RangeSlider extends BaseComponent {
592602
_getConfig(config) {
593603
const dataAttributes = Manipulator.getDataAttributes(this._element)
594604

605+
for (const dataAttribute of Object.keys(dataAttributes)) {
606+
if (DISALLOWED_ATTRIBUTES.has(dataAttribute)) {
607+
delete dataAttributes[dataAttribute]
608+
}
609+
}
610+
595611
config = {
596612
...dataAttributes,
597613
...(typeof config === 'object' && config ? config : {})

0 commit comments

Comments
 (0)