sanitize 6.1.3 → 7.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/{HISTORY.md → CHANGELOG.md} +50 -14
- data/LICENSE +3 -1
- data/README.md +130 -239
- data/lib/sanitize/config/basic.rb +15 -15
- data/lib/sanitize/config/default.rb +45 -45
- data/lib/sanitize/config/relaxed.rb +136 -32
- data/lib/sanitize/config/restricted.rb +2 -2
- data/lib/sanitize/config.rb +12 -14
- data/lib/sanitize/css.rb +403 -308
- data/lib/sanitize/transformers/clean_cdata.rb +9 -9
- data/lib/sanitize/transformers/clean_comment.rb +9 -9
- data/lib/sanitize/transformers/clean_css.rb +59 -55
- data/lib/sanitize/transformers/clean_doctype.rb +15 -15
- data/lib/sanitize/transformers/clean_element.rb +219 -237
- data/lib/sanitize/version.rb +3 -1
- data/lib/sanitize.rb +38 -38
- metadata +15 -56
- data/test/common.rb +0 -3
- data/test/test_clean_comment.rb +0 -47
- data/test/test_clean_css.rb +0 -67
- data/test/test_clean_doctype.rb +0 -71
- data/test/test_clean_element.rb +0 -552
- data/test/test_config.rb +0 -65
- data/test/test_malicious_css.rb +0 -55
- data/test/test_malicious_html.rb +0 -339
- data/test/test_parser.rb +0 -75
- data/test/test_sanitize.rb +0 -197
- data/test/test_sanitize_css.rb +0 -433
- data/test/test_transformers.rb +0 -230
data/README.md
CHANGED
|
@@ -1,21 +1,10 @@
|
|
|
1
|
-
Sanitize
|
|
2
|
-
========
|
|
1
|
+
# Sanitize
|
|
3
2
|
|
|
4
|
-
Sanitize is an allowlist-based HTML and CSS sanitizer. It removes all HTML
|
|
5
|
-
and/or CSS from a string except the elements, attributes, and properties you
|
|
6
|
-
choose to allow.
|
|
3
|
+
Sanitize is an allowlist-based HTML and CSS sanitizer. It removes all HTML and/or CSS from a string except the elements, attributes, and properties you choose to allow.
|
|
7
4
|
|
|
8
|
-
Using a simple configuration syntax, you can tell Sanitize to allow certain HTML
|
|
9
|
-
elements, certain attributes within those elements, and even certain URL
|
|
10
|
-
protocols within attributes that contain URLs. You can also allow specific CSS
|
|
11
|
-
properties, @ rules, and URL protocols in elements or attributes containing CSS.
|
|
12
|
-
Any HTML or CSS that you don't explicitly allow will be removed.
|
|
5
|
+
Using a simple configuration syntax, you can tell Sanitize to allow certain HTML elements, certain attributes within those elements, and even certain URL protocols within attributes that contain URLs. You can also allow specific CSS properties, @ rules, and URL protocols in elements or attributes containing CSS. Any HTML or CSS that you don't explicitly allow will be removed.
|
|
13
6
|
|
|
14
|
-
Sanitize is based on the [Nokogiri HTML5 parser][nokogiri], which parses HTML
|
|
15
|
-
the same way modern browsers do, and [Crass][crass], which parses CSS the same
|
|
16
|
-
way modern browsers do. As long as your allowlist config only allows safe markup
|
|
17
|
-
and CSS, even the most malformed or malicious input will be transformed into
|
|
18
|
-
safe output.
|
|
7
|
+
Sanitize is based on the [Nokogiri HTML5 parser][nokogiri], which parses HTML the same way modern browsers do, and [Crass][crass], which parses CSS the same way modern browsers do. As long as your allowlist config only allows safe markup and CSS, even the most malformed or malicious input will be transformed into safe output.
|
|
19
8
|
|
|
20
9
|
[](http://badge.fury.io/rb/sanitize)
|
|
21
10
|
[](https://github.com/rgrove/sanitize/actions?query=workflow%3ATests)
|
|
@@ -23,24 +12,27 @@ safe output.
|
|
|
23
12
|
[crass]:https://github.com/rgrove/crass
|
|
24
13
|
[nokogiri]:https://github.com/sparklemotion/nokogiri
|
|
25
14
|
|
|
26
|
-
|
|
27
|
-
|
|
15
|
+
> [!WARNING]
|
|
16
|
+
>
|
|
17
|
+
> Sanitize cannot fully sanitize the contents of `<math>` or `<svg>` elements. MathML and SVG elements are [foreign elements](https://html.spec.whatwg.org/multipage/syntax.html#foreign-elements) that don't follow normal HTML parsing rules.
|
|
18
|
+
>
|
|
19
|
+
> By default, Sanitize will remove all MathML and SVG elements. If you add MathML or SVG elements to a custom element allowlist, you may create a security vulnerability in your application.
|
|
20
|
+
|
|
21
|
+
## Links
|
|
28
22
|
|
|
29
23
|
* [Home](https://github.com/rgrove/sanitize/)
|
|
30
|
-
* [API Docs](https://rubydoc.info/
|
|
24
|
+
* [API Docs](https://rubydoc.info/gems/sanitize/Sanitize)
|
|
31
25
|
* [Issues](https://github.com/rgrove/sanitize/issues)
|
|
32
26
|
* [Release History](https://github.com/rgrove/sanitize/releases)
|
|
33
27
|
* [Online Demo](https://sanitize-web.fly.dev/)
|
|
34
28
|
|
|
35
|
-
Installation
|
|
36
|
-
-------------
|
|
29
|
+
## Installation
|
|
37
30
|
|
|
38
31
|
```
|
|
39
32
|
gem install sanitize
|
|
40
33
|
```
|
|
41
34
|
|
|
42
|
-
Quick Start
|
|
43
|
-
-----------
|
|
35
|
+
## Quick Start
|
|
44
36
|
|
|
45
37
|
```ruby
|
|
46
38
|
require 'sanitize'
|
|
@@ -59,8 +51,7 @@ Sanitize::CSS.stylesheet(css, Sanitize::Config::RELAXED)
|
|
|
59
51
|
Sanitize::CSS.properties(css, Sanitize::Config::RELAXED)
|
|
60
52
|
```
|
|
61
53
|
|
|
62
|
-
Usage
|
|
63
|
-
-----
|
|
54
|
+
## Usage
|
|
64
55
|
|
|
65
56
|
Sanitize can sanitize the following types of input:
|
|
66
57
|
|
|
@@ -71,7 +62,7 @@ Sanitize can sanitize the following types of input:
|
|
|
71
62
|
* Standalone CSS stylesheets
|
|
72
63
|
* Standalone CSS properties
|
|
73
64
|
|
|
74
|
-
>
|
|
65
|
+
> [!WARNING]
|
|
75
66
|
>
|
|
76
67
|
> Sanitize cannot fully sanitize the contents of `<math>` or `<svg>` elements. MathML and SVG elements are [foreign elements](https://html.spec.whatwg.org/multipage/syntax.html#foreign-elements) that don't follow normal HTML parsing rules.
|
|
77
68
|
>
|
|
@@ -79,31 +70,26 @@ Sanitize can sanitize the following types of input:
|
|
|
79
70
|
|
|
80
71
|
### HTML Fragments
|
|
81
72
|
|
|
82
|
-
A fragment is a snippet of HTML that doesn't contain a root-level `<html>`
|
|
83
|
-
element.
|
|
73
|
+
A fragment is a snippet of HTML that doesn't contain a root-level `<html>` element.
|
|
84
74
|
|
|
85
|
-
If you don't specify any configuration options, Sanitize will use its strictest
|
|
86
|
-
settings by default, which means it will strip all HTML and leave only safe text
|
|
87
|
-
behind.
|
|
75
|
+
If you don't specify any configuration options, Sanitize will use its strictest settings by default, which means it will strip all HTML and leave only safe text behind.
|
|
88
76
|
|
|
89
77
|
```ruby
|
|
90
78
|
html = '<b><a href="http://foo.com/">foo</a></b><img src="bar.jpg">'
|
|
91
79
|
Sanitize.fragment(html)
|
|
92
|
-
# =>
|
|
80
|
+
# => "foo"
|
|
93
81
|
```
|
|
94
82
|
|
|
95
83
|
To keep certain elements, add them to the element allowlist.
|
|
96
84
|
|
|
97
85
|
```ruby
|
|
98
|
-
Sanitize.fragment(html, :
|
|
99
|
-
# =>
|
|
86
|
+
Sanitize.fragment(html, elements: ['b'])
|
|
87
|
+
# => "<b>foo</b>"
|
|
100
88
|
```
|
|
101
89
|
|
|
102
90
|
### HTML Documents
|
|
103
91
|
|
|
104
|
-
When sanitizing a document, the `<html>` element must be allowlisted. You can
|
|
105
|
-
also set `:allow_doctype` to `true` to allow well-formed document type
|
|
106
|
-
definitions.
|
|
92
|
+
When sanitizing a document, the `<html>` element must be allowlisted. You can also set `:allow_doctype` to `true` to allow well-formed document type definitions.
|
|
107
93
|
|
|
108
94
|
```ruby
|
|
109
95
|
html = %[
|
|
@@ -114,22 +100,15 @@ html = %[
|
|
|
114
100
|
]
|
|
115
101
|
|
|
116
102
|
Sanitize.document(html,
|
|
117
|
-
:
|
|
118
|
-
:
|
|
103
|
+
allow_doctype: true,
|
|
104
|
+
elements: ['html']
|
|
119
105
|
)
|
|
120
|
-
# =>
|
|
121
|
-
# <!DOCTYPE html><html>foo
|
|
122
|
-
#
|
|
123
|
-
# </html>
|
|
124
|
-
# ]
|
|
106
|
+
# => "<!DOCTYPE html><html>foo\n \n</html>"
|
|
125
107
|
```
|
|
126
108
|
|
|
127
109
|
### CSS in HTML
|
|
128
110
|
|
|
129
|
-
To sanitize CSS in an HTML fragment or document, first allowlist the `<style>`
|
|
130
|
-
element and/or the `style` attribute. Then allowlist the CSS properties,
|
|
131
|
-
@ rules, and URL protocols you wish to allow. You can also choose whether to
|
|
132
|
-
allow CSS comments or browser compatibility hacks.
|
|
111
|
+
To sanitize CSS in an HTML fragment or document, first allowlist the `<style>` element and/or the `style` attribute. Then allowlist the CSS properties, @ rules, and URL protocols you wish to allow. You can also choose whether to allow CSS comments or browser compatibility hacks.
|
|
133
112
|
|
|
134
113
|
```ruby
|
|
135
114
|
html = %[
|
|
@@ -142,11 +121,11 @@ html = %[
|
|
|
142
121
|
]
|
|
143
122
|
|
|
144
123
|
Sanitize.fragment(html,
|
|
145
|
-
:
|
|
146
|
-
:
|
|
124
|
+
elements: ['div', 'style'],
|
|
125
|
+
attributes: {'div' => ['style']},
|
|
147
126
|
|
|
148
|
-
:
|
|
149
|
-
:
|
|
127
|
+
css: {
|
|
128
|
+
properties: ['width']
|
|
150
129
|
}
|
|
151
130
|
)
|
|
152
131
|
#=> %[
|
|
@@ -161,8 +140,10 @@ Sanitize.fragment(html,
|
|
|
161
140
|
|
|
162
141
|
### Standalone CSS
|
|
163
142
|
|
|
164
|
-
Sanitize will happily clean up a standalone CSS stylesheet or property string
|
|
165
|
-
|
|
143
|
+
Sanitize will happily clean up a standalone CSS stylesheet or property string without needing to invoke the HTML parser.
|
|
144
|
+
|
|
145
|
+
> [!WARNING]
|
|
146
|
+
> This should only be used to sanitize CSS for use in a standalone CSS file. To safely sanitize CSS for use in an HTML context, such as in a `<style>` element or a `style` attribute, you must use `Sanitize.document()` or `Sanitize.fragment()` with an appropriate allowlist as described in the previous sections. Failure to do so may enable HTML injection attacks.
|
|
166
147
|
|
|
167
148
|
```ruby
|
|
168
149
|
css = %[
|
|
@@ -180,7 +161,6 @@ Sanitize::CSS.stylesheet(css, Sanitize::Config::RELAXED)
|
|
|
180
161
|
# => %[
|
|
181
162
|
#
|
|
182
163
|
#
|
|
183
|
-
#
|
|
184
164
|
# a { text-decoration: none; }
|
|
185
165
|
#
|
|
186
166
|
# a:hover {
|
|
@@ -197,15 +177,11 @@ Sanitize::CSS.properties(%[
|
|
|
197
177
|
#
|
|
198
178
|
# text-decoration: underline;
|
|
199
179
|
# ]
|
|
200
|
-
|
|
201
180
|
```
|
|
202
181
|
|
|
203
|
-
Configuration
|
|
204
|
-
-------------
|
|
182
|
+
## Configuration
|
|
205
183
|
|
|
206
|
-
In addition to the ultra-safe default settings, Sanitize comes with three other
|
|
207
|
-
built-in configurations that you can use out of the box or adapt to meet your
|
|
208
|
-
needs.
|
|
184
|
+
In addition to the ultra-safe default settings, Sanitize comes with three other built-in configurations that you can use out of the box or adapt to meet your needs.
|
|
209
185
|
|
|
210
186
|
### Sanitize::Config::RESTRICTED
|
|
211
187
|
|
|
@@ -213,16 +189,14 @@ Allows only very simple inline markup. No links, images, or block elements.
|
|
|
213
189
|
|
|
214
190
|
```ruby
|
|
215
191
|
Sanitize.fragment(html, Sanitize::Config::RESTRICTED)
|
|
216
|
-
# =>
|
|
192
|
+
# => "<b>foo</b>"
|
|
217
193
|
```
|
|
218
194
|
|
|
219
195
|
### Sanitize::Config::BASIC
|
|
220
196
|
|
|
221
197
|
Allows a variety of markup including formatting elements, links, and lists.
|
|
222
198
|
|
|
223
|
-
Images and tables are not allowed, links are limited to FTP, HTTP, HTTPS, and
|
|
224
|
-
mailto protocols, and a `rel="nofollow"` attribute is added to all links to
|
|
225
|
-
mitigate SEO spam.
|
|
199
|
+
Images and tables are not allowed, links are limited to FTP, HTTP, HTTPS, and mailto protocols, and a `rel="nofollow"` attribute is added to all links to mitigate SEO spam.
|
|
226
200
|
|
|
227
201
|
```ruby
|
|
228
202
|
Sanitize.fragment(html, Sanitize::Config::BASIC)
|
|
@@ -231,10 +205,7 @@ Sanitize.fragment(html, Sanitize::Config::BASIC)
|
|
|
231
205
|
|
|
232
206
|
### Sanitize::Config::RELAXED
|
|
233
207
|
|
|
234
|
-
Allows an even wider variety of markup, including images and tables, as well as
|
|
235
|
-
safe CSS. Links are still limited to FTP, HTTP, HTTPS, and mailto protocols,
|
|
236
|
-
while images are limited to HTTP and HTTPS. In this mode, `rel="nofollow"` is
|
|
237
|
-
not added to links.
|
|
208
|
+
Allows an even wider variety of markup, including images and tables, as well as safe CSS. Links are still limited to FTP, HTTP, HTTPS, and mailto protocols, while images are limited to HTTP and HTTPS. In this mode, `rel="nofollow"` is not added to links.
|
|
238
209
|
|
|
239
210
|
```ruby
|
|
240
211
|
Sanitize.fragment(html, Sanitize::Config::RELAXED)
|
|
@@ -243,50 +214,43 @@ Sanitize.fragment(html, Sanitize::Config::RELAXED)
|
|
|
243
214
|
|
|
244
215
|
### Custom Configuration
|
|
245
216
|
|
|
246
|
-
If the built-in modes don't meet your needs, you can easily specify a custom
|
|
247
|
-
configuration:
|
|
217
|
+
If the built-in modes don't meet your needs, you can easily specify a custom configuration:
|
|
248
218
|
|
|
249
219
|
```ruby
|
|
250
220
|
Sanitize.fragment(html,
|
|
251
|
-
:
|
|
221
|
+
elements: ['a', 'span'],
|
|
252
222
|
|
|
253
|
-
:
|
|
254
|
-
'a'
|
|
223
|
+
attributes: {
|
|
224
|
+
'a' => ['href', 'title'],
|
|
255
225
|
'span' => ['class']
|
|
256
226
|
},
|
|
257
227
|
|
|
258
|
-
:
|
|
228
|
+
protocols: {
|
|
259
229
|
'a' => {'href' => ['http', 'https', 'mailto']}
|
|
260
230
|
}
|
|
261
231
|
)
|
|
262
232
|
```
|
|
263
233
|
|
|
264
|
-
You can also start with one of Sanitize's built-in configurations and then
|
|
265
|
-
customize it to meet your needs.
|
|
234
|
+
You can also start with one of Sanitize's built-in configurations and then customize it to meet your needs.
|
|
266
235
|
|
|
267
|
-
The built-in configs are deeply frozen to prevent people from modifying them
|
|
268
|
-
(either accidentally or maliciously). To customize a built-in config, create a
|
|
269
|
-
new copy using `Sanitize::Config.merge()`, like so:
|
|
236
|
+
The built-in configs are deeply frozen to prevent people from modifying them (either accidentally or maliciously). To customize a built-in config, create a new copy using `Sanitize::Config.merge()`, like so:
|
|
270
237
|
|
|
271
238
|
```ruby
|
|
272
239
|
# Create a customized copy of the Basic config, adding <div> and <table> to the
|
|
273
240
|
# existing allowlisted elements.
|
|
274
241
|
Sanitize.fragment(html, Sanitize::Config.merge(Sanitize::Config::BASIC,
|
|
275
|
-
:
|
|
276
|
-
:
|
|
242
|
+
elements: Sanitize::Config::BASIC[:elements] + ['div', 'table'],
|
|
243
|
+
remove_contents: true
|
|
277
244
|
))
|
|
278
245
|
```
|
|
279
246
|
|
|
280
|
-
The example above adds the `<div>` and `<table>` elements to a copy of the
|
|
281
|
-
existing list of elements in `Sanitize::Config::BASIC`. If you instead want to
|
|
282
|
-
completely overwrite the elements array with your own, you can omit the `+`
|
|
283
|
-
operation:
|
|
247
|
+
The example above adds the `<div>` and `<table>` elements to a copy of the existing list of elements in `Sanitize::Config::BASIC`. If you instead want to completely overwrite the elements array with your own, you can omit the `+` operation:
|
|
284
248
|
|
|
285
249
|
```ruby
|
|
286
250
|
# Overwrite :elements instead of creating a copy with new entries.
|
|
287
251
|
Sanitize.fragment(html, Sanitize::Config.merge(Sanitize::Config::BASIC,
|
|
288
|
-
:
|
|
289
|
-
:
|
|
252
|
+
elements: ['div', 'table'],
|
|
253
|
+
remove_contents: true
|
|
290
254
|
))
|
|
291
255
|
```
|
|
292
256
|
|
|
@@ -294,66 +258,56 @@ Sanitize.fragment(html, Sanitize::Config.merge(Sanitize::Config::BASIC,
|
|
|
294
258
|
|
|
295
259
|
#### :add_attributes (Hash)
|
|
296
260
|
|
|
297
|
-
Attributes to add to specific elements. If the attribute already exists, it will
|
|
298
|
-
be replaced with the value specified here. Specify all element names and
|
|
299
|
-
attributes in lowercase.
|
|
261
|
+
Attributes to add to specific elements. If the attribute already exists, it will be replaced with the value specified here. Specify all element names and attributes in lowercase.
|
|
300
262
|
|
|
301
263
|
```ruby
|
|
302
|
-
:
|
|
264
|
+
add_attributes: {
|
|
303
265
|
'a' => {'rel' => 'nofollow'}
|
|
304
266
|
}
|
|
305
267
|
```
|
|
306
268
|
|
|
307
269
|
#### :allow_comments (boolean)
|
|
308
270
|
|
|
309
|
-
Whether or not to allow HTML comments. Allowing comments is strongly
|
|
310
|
-
discouraged, since IE allows script execution within conditional comments. The
|
|
311
|
-
default value is `false`.
|
|
271
|
+
Whether or not to allow HTML comments. Allowing comments is strongly discouraged, since IE allows script execution within conditional comments. The default value is `false`.
|
|
312
272
|
|
|
313
273
|
#### :allow_doctype (boolean)
|
|
314
274
|
|
|
315
|
-
Whether or not to allow well-formed HTML doctype declarations such as "<!DOCTYPE
|
|
316
|
-
html>" when sanitizing a document. This setting is ignored when sanitizing
|
|
317
|
-
fragments. The default value is `false`.
|
|
275
|
+
Whether or not to allow well-formed HTML doctype declarations such as "<!DOCTYPE html>" when sanitizing a document. This setting is ignored when sanitizing fragments. The default value is `false`.
|
|
318
276
|
|
|
319
277
|
#### :attributes (Hash)
|
|
320
278
|
|
|
321
|
-
Attributes to allow on specific elements. Specify all element names and
|
|
322
|
-
attributes in lowercase.
|
|
279
|
+
Attributes to allow on specific elements. Specify all element names and attributes in lowercase.
|
|
323
280
|
|
|
324
281
|
```ruby
|
|
325
|
-
:
|
|
326
|
-
'a'
|
|
282
|
+
attributes: {
|
|
283
|
+
'a' => ['href', 'title'],
|
|
327
284
|
'blockquote' => ['cite'],
|
|
328
|
-
'img'
|
|
285
|
+
'img' => ['alt', 'src', 'title']
|
|
329
286
|
}
|
|
330
287
|
```
|
|
331
288
|
|
|
332
|
-
If you'd like to allow certain attributes on all elements, use the symbol `:all`
|
|
333
|
-
instead of an element name.
|
|
289
|
+
If you'd like to allow certain attributes on all elements, use the symbol `:all` instead of an element name.
|
|
334
290
|
|
|
335
291
|
```ruby
|
|
336
292
|
# Allow the class attribute on all elements.
|
|
337
|
-
:
|
|
293
|
+
attributes: {
|
|
338
294
|
:all => ['class'],
|
|
339
|
-
'a'
|
|
295
|
+
'a' => ['href', 'title']
|
|
340
296
|
}
|
|
341
297
|
```
|
|
342
298
|
|
|
343
|
-
To allow arbitrary HTML5 `data-*` attributes, use the symbol `:data` in place of
|
|
344
|
-
an attribute name.
|
|
299
|
+
To allow arbitrary HTML5 `data-*` attributes, use the symbol `:data` in place of an attribute name.
|
|
345
300
|
|
|
346
301
|
```ruby
|
|
347
302
|
# Allow arbitrary HTML5 data-* attributes on <div> elements.
|
|
348
|
-
:
|
|
303
|
+
attributes: {
|
|
349
304
|
'div' => [:data]
|
|
350
305
|
}
|
|
351
306
|
```
|
|
352
307
|
|
|
353
308
|
#### :css (Hash)
|
|
354
309
|
|
|
355
|
-
Hash of the following CSS config settings to be used when sanitizing CSS (either
|
|
356
|
-
standalone or embedded in HTML).
|
|
310
|
+
Hash of the following CSS config settings to be used when sanitizing CSS (either standalone or embedded in HTML).
|
|
357
311
|
|
|
358
312
|
##### :css => :allow_comments (boolean)
|
|
359
313
|
|
|
@@ -361,36 +315,27 @@ Whether or not to allow CSS comments. The default value is `false`.
|
|
|
361
315
|
|
|
362
316
|
##### :css => :allow_hacks (boolean)
|
|
363
317
|
|
|
364
|
-
Whether or not to allow browser compatibility hacks such as the IE `*` and `_`
|
|
365
|
-
hacks. These are generally harmless, but technically result in invalid CSS. The
|
|
366
|
-
default is `false`.
|
|
318
|
+
Whether or not to allow browser compatibility hacks such as the IE `*` and `_` hacks. These are generally harmless, but technically result in invalid CSS. The default is `false`.
|
|
367
319
|
|
|
368
320
|
##### :css => :at_rules (Array or Set)
|
|
369
321
|
|
|
370
|
-
Names of CSS [at-rules][at-rules] to allow that may not have associated blocks,
|
|
371
|
-
such as `import` or `charset`. Names should be specified in lowercase.
|
|
322
|
+
Names of CSS [at-rules][at-rules] to allow that may not have associated blocks, such as `import` or `charset`. Names should be specified in lowercase.
|
|
372
323
|
|
|
373
324
|
[at-rules]:https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule
|
|
374
325
|
|
|
375
326
|
##### :css => :at_rules_with_properties (Array or Set)
|
|
376
327
|
|
|
377
|
-
Names of CSS [at-rules][at-rules] to allow that may have associated blocks
|
|
378
|
-
containing CSS properties. At-rules like `font-face` and `page` fall into this
|
|
379
|
-
category. Names should be specified in lowercase.
|
|
328
|
+
Names of CSS [at-rules][at-rules] to allow that may have associated blocks containing CSS properties. At-rules like `font-face` and `page` fall into this category. Names should be specified in lowercase.
|
|
380
329
|
|
|
381
330
|
##### :css => :at_rules_with_styles (Array or Set)
|
|
382
331
|
|
|
383
|
-
Names of CSS [at-rules][at-rules] to allow that may have associated blocks
|
|
384
|
-
containing style rules. At-rules like `media` and `keyframes` fall into this
|
|
385
|
-
category. Names should be specified in lowercase.
|
|
332
|
+
Names of CSS [at-rules][at-rules] to allow that may have associated blocks containing style rules. At-rules like `media` and `keyframes` fall into this category. Names should be specified in lowercase.
|
|
386
333
|
|
|
387
334
|
##### :css => :import_url_validator
|
|
388
335
|
|
|
389
|
-
This is a `Proc` (or other callable object) that will be called and passed
|
|
390
|
-
the URL specified for any `@import` [at-rules][at-rules].
|
|
336
|
+
This is a `Proc` (or other callable object) that will be called and passed the URL specified for any `@import` [at-rules][at-rules].
|
|
391
337
|
|
|
392
|
-
You can use this to limit what can be imported, for example something
|
|
393
|
-
like the following to limit `@import` to Google Fonts URLs:
|
|
338
|
+
You can use this to limit what can be imported, for example something like the following to limit `@import` to Google Fonts URLs:
|
|
394
339
|
|
|
395
340
|
```ruby
|
|
396
341
|
Proc.new { |url| url.start_with?("https://fonts.googleapis.com") }
|
|
@@ -404,28 +349,26 @@ List of CSS property names to allow. Names should be specified in lowercase.
|
|
|
404
349
|
|
|
405
350
|
URL protocols to allow in CSS URLs. Should be specified in lowercase.
|
|
406
351
|
|
|
407
|
-
If you'd like to allow the use of relative URLs which don't have a protocol,
|
|
408
|
-
include the symbol `:relative` in the protocol array.
|
|
352
|
+
If you'd like to allow the use of relative URLs which don't have a protocol, include the symbol `:relative` in the protocol array.
|
|
409
353
|
|
|
410
354
|
#### :elements (Array or Set)
|
|
411
355
|
|
|
412
|
-
Array of HTML element names to allow. Specify all names in lowercase. Any
|
|
413
|
-
elements not in this array will be removed.
|
|
356
|
+
Array of HTML element names to allow. Specify all names in lowercase. Any elements not in this array will be removed.
|
|
414
357
|
|
|
415
358
|
```ruby
|
|
416
|
-
:
|
|
359
|
+
elements: %w[
|
|
417
360
|
a abbr b blockquote br cite code dd dfn dl dt em i kbd li mark ol p pre
|
|
418
361
|
q s samp small strike strong sub sup time u ul var
|
|
419
362
|
]
|
|
420
363
|
```
|
|
421
364
|
|
|
422
|
-
>
|
|
365
|
+
> [!WARNING]
|
|
423
366
|
>
|
|
424
367
|
> Sanitize cannot fully sanitize the contents of `<math>` or `<svg>` elements. MathML and SVG elements are [foreign elements](https://html.spec.whatwg.org/multipage/syntax.html#foreign-elements) that don't follow normal HTML parsing rules.
|
|
425
368
|
>
|
|
426
369
|
> By default, Sanitize will remove all MathML and SVG elements. If you add MathML or SVG elements to a custom element allowlist, you must assume that any content inside them will be allowed, even if that content would otherwise be removed or escaped by Sanitize. This may create a security vulnerability in your application.
|
|
427
370
|
|
|
428
|
-
>
|
|
371
|
+
> [!NOTE]
|
|
429
372
|
>
|
|
430
373
|
> Sanitize always removes `<noscript>` elements and their contents, even if `noscript` is in the allowlist.
|
|
431
374
|
>
|
|
@@ -433,10 +376,10 @@ elements not in this array will be removed.
|
|
|
433
376
|
|
|
434
377
|
#### :parser_options (Hash)
|
|
435
378
|
|
|
436
|
-
[Parsing options](https://
|
|
379
|
+
[Parsing options](https://nokogiri.org/tutorials/parsing_an_html5_document.html?h=parsing+options#parsing-options) to be supplied to Nokogiri.
|
|
437
380
|
|
|
438
381
|
```ruby
|
|
439
|
-
:
|
|
382
|
+
parser_options: {
|
|
440
383
|
max_errors: -1,
|
|
441
384
|
max_tree_depth: -1
|
|
442
385
|
}
|
|
@@ -444,81 +387,59 @@ elements not in this array will be removed.
|
|
|
444
387
|
|
|
445
388
|
#### :protocols (Hash)
|
|
446
389
|
|
|
447
|
-
URL protocols to allow in specific attributes. If an attribute is listed here
|
|
448
|
-
and contains a protocol other than those specified (or if it contains no
|
|
449
|
-
protocol at all), it will be removed.
|
|
390
|
+
URL protocols to allow in specific attributes. If an attribute is listed here and contains a protocol other than those specified (or if it contains no protocol at all), it will be removed.
|
|
450
391
|
|
|
451
392
|
```ruby
|
|
452
|
-
:
|
|
453
|
-
'a'
|
|
454
|
-
'img' => {'src'
|
|
393
|
+
protocols: {
|
|
394
|
+
'a' => {'href' => ['ftp', 'http', 'https', 'mailto']},
|
|
395
|
+
'img' => {'src' => ['http', 'https']}
|
|
455
396
|
}
|
|
456
397
|
```
|
|
457
398
|
|
|
458
|
-
If you'd like to allow the use of relative URLs which don't have a protocol,
|
|
459
|
-
include the symbol `:relative` in the protocol array:
|
|
399
|
+
If you'd like to allow the use of relative URLs which don't have a protocol, include the symbol `:relative` in the protocol array:
|
|
460
400
|
|
|
461
401
|
```ruby
|
|
462
|
-
:
|
|
402
|
+
protocols: {
|
|
463
403
|
'a' => {'href' => ['http', 'https', :relative]}
|
|
464
404
|
}
|
|
465
405
|
```
|
|
466
406
|
|
|
467
407
|
#### :remove_contents (boolean or Array or Set)
|
|
468
408
|
|
|
469
|
-
If this is `true`, Sanitize will remove the contents of any non-allowlisted
|
|
470
|
-
elements in addition to the elements themselves. By default, Sanitize leaves the
|
|
471
|
-
safe parts of an element's contents behind when the element is removed.
|
|
409
|
+
If this is `true`, Sanitize will remove the contents of any non-allowlisted elements in addition to the elements themselves. By default, Sanitize leaves the safe parts of an element's contents behind when the element is removed.
|
|
472
410
|
|
|
473
|
-
If this is an Array or Set of element names, then only the contents of the
|
|
474
|
-
specified elements (when filtered) will be removed, and the contents of all
|
|
475
|
-
other filtered elements will be left behind.
|
|
411
|
+
If this is an Array or Set of element names, then only the contents of the specified elements (when filtered) will be removed, and the contents of all other filtered elements will be left behind.
|
|
476
412
|
|
|
477
|
-
The default value
|
|
413
|
+
The default value can be seen in the [default config](lib/sanitize/config/default.rb).
|
|
478
414
|
|
|
479
415
|
#### :transformers (Array or callable)
|
|
480
416
|
|
|
481
|
-
Custom HTML transformer or array of custom transformers. See the Transformers
|
|
482
|
-
section below for details.
|
|
417
|
+
Custom HTML transformer or array of custom transformers. See the Transformers section below for details.
|
|
483
418
|
|
|
484
419
|
#### :whitespace_elements (Hash)
|
|
485
420
|
|
|
486
|
-
Hash of element names which, when removed, should have their contents surrounded
|
|
487
|
-
by whitespace to preserve readability.
|
|
421
|
+
Hash of element names which, when removed, should have their contents surrounded by whitespace to preserve readability.
|
|
488
422
|
|
|
489
|
-
Each element name is a key pointing to another Hash, which provides the specific
|
|
490
|
-
whitespace that should be inserted `:before` and `:after` the removed element's
|
|
491
|
-
position. The `:after` value will only be inserted if the removed element has
|
|
492
|
-
children, in which case it will be inserted after those children.
|
|
423
|
+
Each element name is a key pointing to another Hash, which provides the specific whitespace that should be inserted `:before` and `:after` the removed element's position. The `:after` value will only be inserted if the removed element has children, in which case it will be inserted after those children.
|
|
493
424
|
|
|
494
425
|
```ruby
|
|
495
|
-
:
|
|
496
|
-
'br'
|
|
497
|
-
'div' => { :
|
|
498
|
-
'p'
|
|
426
|
+
whitespace_elements: {
|
|
427
|
+
'br' => { before: "\n", after: "" },
|
|
428
|
+
'div' => { before: "\n", after: "\n" },
|
|
429
|
+
'p' => { before: "\n", after: "\n" }
|
|
499
430
|
}
|
|
500
431
|
```
|
|
501
432
|
|
|
502
|
-
The default elements with whitespace added before and after
|
|
503
|
-
|
|
504
|
-
```
|
|
505
|
-
address article aside blockquote br dd div dl dt
|
|
506
|
-
footer h1 h2 h3 h4 h5 h6 header hgroup hr li nav
|
|
507
|
-
ol p pre section ul
|
|
508
|
-
|
|
509
|
-
```
|
|
433
|
+
The default elements with whitespace added before and after can be seen in [the default config](lib/sanitize/config/default.rb).
|
|
510
434
|
|
|
511
435
|
## Transformers
|
|
512
436
|
|
|
513
|
-
Transformers allow you to filter and modify HTML nodes using your own custom
|
|
514
|
-
logic, on top of (or instead of) Sanitize's core filter. A transformer is any
|
|
515
|
-
object that responds to `call()` (such as a lambda or proc).
|
|
437
|
+
Transformers allow you to filter and modify HTML nodes using your own custom logic, on top of (or instead of) Sanitize's core filter. A transformer is any object that responds to `call()` (such as a lambda or proc).
|
|
516
438
|
|
|
517
|
-
To use one or more transformers, pass them to the `:transformers` config
|
|
518
|
-
setting. You may pass a single transformer or an array of transformers.
|
|
439
|
+
To use one or more transformers, pass them to the `:transformers` config setting. You may pass a single transformer or an array of transformers.
|
|
519
440
|
|
|
520
441
|
```ruby
|
|
521
|
-
Sanitize.fragment(html, :
|
|
442
|
+
Sanitize.fragment(html, transformers: [
|
|
522
443
|
transformer_one,
|
|
523
444
|
transformer_two
|
|
524
445
|
])
|
|
@@ -526,56 +447,31 @@ Sanitize.fragment(html, :transformers => [
|
|
|
526
447
|
|
|
527
448
|
### Input
|
|
528
449
|
|
|
529
|
-
Each transformer's `call()` method will be called once for each node in the HTML
|
|
530
|
-
(including elements, text nodes, comments, etc.), and will receive as an
|
|
531
|
-
argument a Hash that contains the following items:
|
|
450
|
+
Each transformer's `call()` method will be called once for each node in the HTML (including elements, text nodes, comments, etc.), and will receive as an argument a Hash that contains the following items:
|
|
532
451
|
|
|
533
452
|
* **:config** - The current Sanitize configuration Hash.
|
|
534
453
|
|
|
535
|
-
* **:is_allowlisted** - `true` if the current node has been allowlisted by a
|
|
536
|
-
previous transformer, `false` otherwise. It's generally bad form to remove
|
|
537
|
-
a node that a previous transformer has allowlisted.
|
|
454
|
+
* **:is_allowlisted** - `true` if the current node has been allowlisted by a previous transformer, `false` otherwise. It's generally bad form to remove a node that a previous transformer has allowlisted.
|
|
538
455
|
|
|
539
|
-
* **:node** - A `Nokogiri::XML::Node` object representing an HTML node. The
|
|
540
|
-
node may be an element, a text node, a comment, a CDATA node, or a document
|
|
541
|
-
fragment. Use Nokogiri's inspection methods (`element?`, `text?`, etc.) to
|
|
542
|
-
selectively ignore node types you aren't interested in.
|
|
456
|
+
* **:node** - A `Nokogiri::XML::Node` object representing an HTML node. The node may be an element, a text node, a comment, a CDATA node, or a document fragment. Use Nokogiri's inspection methods (`element?`, `text?`, etc.) to selectively ignore node types you aren't interested in.
|
|
543
457
|
|
|
544
|
-
* **:node_allowlist** - Set of `Nokogiri::XML::Node` objects in the current
|
|
545
|
-
document that have been allowlisted by previous transformers, if any. It's
|
|
546
|
-
generally bad form to remove a node that a previous transformer has
|
|
547
|
-
allowlisted.
|
|
458
|
+
* **:node_allowlist** - Set of `Nokogiri::XML::Node` objects in the current document that have been allowlisted by previous transformers, if any. It's generally bad form to remove a node that a previous transformer has allowlisted.
|
|
548
459
|
|
|
549
|
-
* **:node_name** - The name of the current HTML node, always lowercase (e.g.
|
|
550
|
-
"div" or "span"). For non-element nodes, the name will be something like
|
|
551
|
-
"text", "comment", "#cdata-section", "#document-fragment", etc.
|
|
460
|
+
* **:node_name** - The name of the current HTML node, always lowercase (e.g. "div" or "span"). For non-element nodes, the name will be something like "text", "comment", "#cdata-section", "#document-fragment", etc.
|
|
552
461
|
|
|
553
462
|
### Output
|
|
554
463
|
|
|
555
|
-
A transformer doesn't have to return anything, but may optionally return a Hash,
|
|
556
|
-
which may contain the following items:
|
|
464
|
+
A transformer doesn't have to return anything, but may optionally return a Hash, which may contain the following items:
|
|
557
465
|
|
|
558
|
-
* **:node_allowlist** - Array or Set of specific `Nokogiri::XML::Node`
|
|
559
|
-
objects to add to the document's allowlist, bypassing the current Sanitize
|
|
560
|
-
config. These specific nodes and all their attributes will be allowlisted,
|
|
561
|
-
but their children will not be.
|
|
466
|
+
* **:node_allowlist** - Array or Set of specific `Nokogiri::XML::Node` objects to add to the document's allowlist, bypassing the current Sanitize config. These specific nodes and all their attributes will be allowlisted, but their children will not be.
|
|
562
467
|
|
|
563
|
-
If a transformer returns anything other than a Hash, the return value will be
|
|
564
|
-
ignored.
|
|
468
|
+
If a transformer returns anything other than a Hash, the return value will be ignored.
|
|
565
469
|
|
|
566
470
|
### Processing
|
|
567
471
|
|
|
568
|
-
Each transformer has full access to the `Nokogiri::XML::Node` that's passed into
|
|
569
|
-
it and to the rest of the document via the node's `document()` method. Any
|
|
570
|
-
changes made to the current node or to the document will be reflected instantly
|
|
571
|
-
in the document and passed on to subsequently called transformers and to
|
|
572
|
-
Sanitize itself. A transformer may even call Sanitize internally to perform
|
|
573
|
-
custom sanitization if needed.
|
|
472
|
+
Each transformer has full access to the `Nokogiri::XML::Node` that's passed into it and to the rest of the document via the node's `document()` method. Any changes made to the current node or to the document will be reflected instantly in the document and passed on to subsequently called transformers and to Sanitize itself. A transformer may even call Sanitize internally to perform custom sanitization if needed.
|
|
574
473
|
|
|
575
|
-
Nodes are passed into transformers in the order in which they're traversed.
|
|
576
|
-
Sanitize performs top-down traversal, meaning that nodes are traversed in the
|
|
577
|
-
same order you'd read them in the HTML, starting at the top node, then its first
|
|
578
|
-
child, and so on.
|
|
474
|
+
Nodes are passed into transformers in the order in which they're traversed. Sanitize performs top-down traversal, meaning that nodes are traversed in the same order you'd read them in the HTML, starting at the top node, then its first child, and so on.
|
|
579
475
|
|
|
580
476
|
```ruby
|
|
581
477
|
html = %[
|
|
@@ -594,81 +490,76 @@ transformer = lambda do |env|
|
|
|
594
490
|
end
|
|
595
491
|
|
|
596
492
|
# Prints "header", "span", "strong", "p", "footer".
|
|
597
|
-
Sanitize.fragment(html, :
|
|
493
|
+
Sanitize.fragment(html, transformers: transformer)
|
|
598
494
|
```
|
|
599
495
|
|
|
600
|
-
Transformers have a tremendous amount of power, including the power to
|
|
601
|
-
completely bypass Sanitize's built-in filtering. Be careful! Your safety is in
|
|
602
|
-
your own hands.
|
|
496
|
+
Transformers have a tremendous amount of power, including the power to completely bypass Sanitize's built-in filtering. Be careful! Your safety is in your own hands.
|
|
603
497
|
|
|
604
498
|
### Example: Transformer to allow image URLs by domain
|
|
605
499
|
|
|
606
|
-
The following example demonstrates how to remove image elements unless they use
|
|
607
|
-
a relative URL or are hosted on a specific domain. It assumes that the `<img>`
|
|
608
|
-
element and its `src` attribute are already allowlisted.
|
|
500
|
+
The following example demonstrates how to remove image elements unless they use a relative URL or are hosted on a specific domain. It assumes that the `<img>` element and its `src` attribute are already allowlisted.
|
|
609
501
|
|
|
610
502
|
```ruby
|
|
611
|
-
require
|
|
503
|
+
require "uri"
|
|
612
504
|
|
|
613
505
|
image_allowlist_transformer = lambda do |env|
|
|
614
506
|
# Ignore everything except <img> elements.
|
|
615
|
-
return unless env[:node_name] ==
|
|
507
|
+
return unless env[:node_name] == "img"
|
|
616
508
|
|
|
617
|
-
node
|
|
618
|
-
image_uri = URI.parse(node[
|
|
509
|
+
node = env[:node]
|
|
510
|
+
image_uri = URI.parse(node["src"])
|
|
619
511
|
|
|
620
512
|
# Only allow relative URLs or URLs with the example.com domain. The
|
|
621
513
|
# image_uri.host.nil? check ensures that protocol-relative URLs like
|
|
622
|
-
# "//evil.com/foo.jpg".
|
|
623
|
-
unless image_uri.host ==
|
|
624
|
-
|
|
514
|
+
# "//evil.com/foo.jpg" are not allowed.
|
|
515
|
+
unless image_uri.host == "example.com"
|
|
516
|
+
unless image_uri.host.nil? && image_uri.relative?
|
|
517
|
+
node.unlink # `Nokogiri::XML::Node#unlink` removes a node from the document
|
|
518
|
+
end
|
|
625
519
|
end
|
|
626
520
|
end
|
|
627
521
|
```
|
|
628
522
|
|
|
629
523
|
### Example: Transformer to allow YouTube video embeds
|
|
630
524
|
|
|
631
|
-
The following example demonstrates how to create a transformer that will safely
|
|
632
|
-
allow valid YouTube video embeds without having to allow other kinds of embedded
|
|
633
|
-
content, which would be the case if you tried to do this by just allowing all
|
|
634
|
-
`<iframe>` elements:
|
|
525
|
+
The following example demonstrates how to create a transformer that will safely allow valid YouTube video embeds without having to allow other kinds of embedded content, which would be the case if you tried to do this by just allowing all `<iframe>` elements:
|
|
635
526
|
|
|
636
527
|
```ruby
|
|
637
528
|
youtube_transformer = lambda do |env|
|
|
638
|
-
node
|
|
529
|
+
node = env[:node]
|
|
639
530
|
node_name = env[:node_name]
|
|
640
531
|
|
|
641
532
|
# Don't continue if this node is already allowlisted or is not an element.
|
|
642
533
|
return if env[:is_allowlisted] || !node.element?
|
|
643
534
|
|
|
644
535
|
# Don't continue unless the node is an iframe.
|
|
645
|
-
return unless node_name ==
|
|
536
|
+
return unless node_name == "iframe"
|
|
646
537
|
|
|
647
538
|
# Verify that the video URL is actually a valid YouTube video URL.
|
|
648
|
-
return unless
|
|
539
|
+
return unless %r{\A(?:https?:)?//(?:www\.)?youtube(?:-nocookie)?\.com/}.match?(node["src"])
|
|
649
540
|
|
|
650
541
|
# We're now certain that this is a YouTube embed, but we still need to run
|
|
651
542
|
# it through a special Sanitize step to ensure that no unwanted elements or
|
|
652
543
|
# attributes that don't belong in a YouTube embed can sneak in.
|
|
653
544
|
Sanitize.node!(node, {
|
|
654
|
-
:
|
|
545
|
+
elements: %w[iframe],
|
|
655
546
|
|
|
656
|
-
:
|
|
657
|
-
|
|
547
|
+
attributes: {
|
|
548
|
+
"iframe" => %w[allowfullscreen frameborder height src width]
|
|
658
549
|
}
|
|
659
550
|
})
|
|
660
551
|
|
|
661
552
|
# Now that we're sure that this is a valid YouTube embed and that there are
|
|
662
553
|
# no unwanted elements or attributes hidden inside it, we can tell Sanitize
|
|
663
554
|
# to allowlist the current node.
|
|
664
|
-
{:
|
|
555
|
+
{node_allowlist: [node]}
|
|
665
556
|
end
|
|
666
557
|
|
|
667
558
|
html = %[
|
|
668
559
|
<iframe width="420" height="315" src="//www.youtube.com/embed/dQw4w9WgXcQ"
|
|
669
560
|
frameborder="0" allowfullscreen></iframe>
|
|
670
|
-
]
|
|
561
|
+
].strip
|
|
671
562
|
|
|
672
|
-
Sanitize.fragment(html, :
|
|
563
|
+
Sanitize.fragment(html, transformers: youtube_transformer)
|
|
673
564
|
# => '<iframe width="420" height="315" src="//www.youtube.com/embed/dQw4w9WgXcQ" frameborder="0" allowfullscreen=""></iframe>'
|
|
674
565
|
```
|