sanitize-html 2.2.0 → 2.3.3
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.
- package/CHANGELOG.md +15 -0
- package/README.md +5 -3
- package/index.js +27 -18
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.3.3 (2021-03-19):
|
|
4
|
+
- Security fix: `allowedSchemes` and related options did not properly block schemes containing a hyphen, plus sign, period or digit, such as `ms-calculator:`. Thanks to Lukas Euler for pointing out the issue.
|
|
5
|
+
- Added a security note about the known risks associated with using the `parser` option, especially `decodeEntities: false`. See the documentation.
|
|
6
|
+
|
|
7
|
+
## 2.3.2 (2021-01-26):
|
|
8
|
+
|
|
9
|
+
- Additional fixes for iframe validation exploits. Prevent exploits based on browsers' tolerance of the use of "\" rather than "/" and the presence of whitespace at this point in the URL. Thanks to Ron Masas of [Checkmarx](https://www.checkmarx.com/) for pointing out the issue and writing unit tests.
|
|
10
|
+
- Updates README `yarn add` syntax. Thanks to [Tagir Khadshiev](https://github.com/Aspedm) for the contribution.
|
|
11
|
+
|
|
12
|
+
## 2.3.1 (2021-01-22):
|
|
13
|
+
- Uses the standard WHATWG URL parser to stop IDNA (Internationalized Domain Name) attacks on the iframe hostname validator. Thanks to Ron Masas of [Checkmarx](https://www.checkmarx.com/) for pointing out the issue and suggesting the use of the WHATWG parser.
|
|
14
|
+
|
|
15
|
+
## 2.3.0 (2020-12-16):
|
|
16
|
+
- Upgrades `htmlparser2` to new major version `^6.0.0`. Thanks to [Bogdan Chadkin](https://github.com/TrySound) for the contribution.
|
|
17
|
+
|
|
3
18
|
## 2.2.0 (2020-12-02):
|
|
4
19
|
- Adds a note to the README about Typescript support (or the lack-thereof).
|
|
5
20
|
- Adds `tel` to the default `allowedSchemes`. Thanks to [Arne Herbots](https://github.com/aHerbots) for this contribution.
|
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ HTML comments are not preserved.
|
|
|
24
24
|
|
|
25
25
|
## Requirements
|
|
26
26
|
|
|
27
|
-
sanitize-html is intended for use with Node.
|
|
27
|
+
sanitize-html is intended for use with Node.js and supports Node 10+. All of its npm dependencies are pure JavaScript. sanitize-html is built on the excellent `htmlparser2` module.
|
|
28
28
|
|
|
29
29
|
### Regarding Typescript
|
|
30
30
|
|
|
@@ -42,7 +42,7 @@ But, perhaps you'd like to display sanitized HTML immediately in the browser for
|
|
|
42
42
|
* Run npm install and:
|
|
43
43
|
|
|
44
44
|
```bash
|
|
45
|
-
npm install sanitize-html # yarn
|
|
45
|
+
npm install sanitize-html # yarn add sanitize-html
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
The primary change in the 2.x version of sanitize-html is that it no longer includes a build that is ready for browser use. Developers are expected to include sanitize-html in their project builds (e.g., webpack) as they would any other dependency. So while sanitize-html is no longer ready to link to directly in HTML, developers can now more easily process it according to their needs.
|
|
@@ -274,7 +274,9 @@ enforceHtmlBoundary: true
|
|
|
274
274
|
|
|
275
275
|
### htmlparser2 Options
|
|
276
276
|
|
|
277
|
-
sanitize-html is built on `htmlparser2`. By default the only option passed down is `decodeEntities: true
|
|
277
|
+
sanitize-html is built on `htmlparser2`. By default the only option passed down is `decodeEntities: true`. You can set the options to pass by using the parser option.
|
|
278
|
+
|
|
279
|
+
**Security note: changing the `parser` settings can be risky.** In particular, `decodeEntities: false` has known security concerns and a complete test suite does not exist for every possible combination of settings when used with `sanitize-html`. If security is your goal we recommend you use the defaults rather than changing `parser`, except for the `lowerCaseTags` option.
|
|
278
280
|
|
|
279
281
|
```javascript
|
|
280
282
|
const clean = sanitizeHtml(dirty, {
|
package/index.js
CHANGED
|
@@ -5,7 +5,6 @@ const { isPlainObject } = require('is-plain-object');
|
|
|
5
5
|
const deepmerge = require('deepmerge');
|
|
6
6
|
const parseSrcset = require('parse-srcset');
|
|
7
7
|
const { parse: postcssParse } = require('postcss');
|
|
8
|
-
const url = require('url');
|
|
9
8
|
// Tags that can conceivably represent stand-alone media.
|
|
10
9
|
const mediaTags = [
|
|
11
10
|
'img', 'audio', 'video', 'picture', 'svg',
|
|
@@ -109,17 +108,9 @@ function sanitizeHtml(html, options, _recursing) {
|
|
|
109
108
|
};
|
|
110
109
|
}
|
|
111
110
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
} else {
|
|
116
|
-
options = Object.assign({}, sanitizeHtml.defaults, options);
|
|
117
|
-
if (options.parser) {
|
|
118
|
-
options.parser = Object.assign({}, htmlParserDefaults, options.parser);
|
|
119
|
-
} else {
|
|
120
|
-
options.parser = htmlParserDefaults;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
111
|
+
options = Object.assign({}, sanitizeHtml.defaults, options);
|
|
112
|
+
options.parser = Object.assign({}, htmlParserDefaults, options.parser);
|
|
113
|
+
|
|
123
114
|
// vulnerableTags
|
|
124
115
|
vulnerableTags.forEach(function (tag) {
|
|
125
116
|
if (
|
|
@@ -313,12 +304,28 @@ function sanitizeHtml(html, options, _recursing) {
|
|
|
313
304
|
if (name === 'iframe' && a === 'src') {
|
|
314
305
|
let allowed = true;
|
|
315
306
|
try {
|
|
307
|
+
// Chrome accepts \ as a substitute for / in the // at the
|
|
308
|
+
// start of a URL, so rewrite accordingly to prevent exploit.
|
|
309
|
+
// Also drop any whitespace at that point in the URL
|
|
310
|
+
value = value.replace(/^(\w+:)?\s*[\\/]\s*[\\/]/, '$1//');
|
|
311
|
+
if (value.startsWith('relative:')) {
|
|
312
|
+
// An attempt to exploit our workaround for base URLs being
|
|
313
|
+
// mandatory for relative URL validation in the WHATWG
|
|
314
|
+
// URL parser, reject it
|
|
315
|
+
throw new Error('relative: exploit attempt');
|
|
316
|
+
}
|
|
316
317
|
// naughtyHref is in charge of whether protocol relative URLs
|
|
317
|
-
// are cool.
|
|
318
|
-
//
|
|
319
|
-
//
|
|
320
|
-
|
|
321
|
-
|
|
318
|
+
// are cool. Here we are concerned just with allowed hostnames and
|
|
319
|
+
// whether to allow relative URLs.
|
|
320
|
+
//
|
|
321
|
+
// Build a placeholder "base URL" against which any reasonable
|
|
322
|
+
// relative URL may be parsed successfully
|
|
323
|
+
let base = 'relative://relative-site';
|
|
324
|
+
for (let i = 0; (i < 100); i++) {
|
|
325
|
+
base += `/${i}`;
|
|
326
|
+
}
|
|
327
|
+
const parsed = new URL(value, base);
|
|
328
|
+
const isRelativeUrl = parsed && parsed.hostname === 'relative-site' && parsed.protocol === 'relative:';
|
|
322
329
|
if (isRelativeUrl) {
|
|
323
330
|
// default value of allowIframeRelativeUrls is true
|
|
324
331
|
// unless allowedIframeHostnames or allowedIframeDomains specified
|
|
@@ -561,7 +568,9 @@ function sanitizeHtml(html, options, _recursing) {
|
|
|
561
568
|
// a javascript: URL to be snuck through
|
|
562
569
|
href = href.replace(/<!--.*?-->/g, '');
|
|
563
570
|
// Case insensitive so we don't get faked out by JAVASCRIPT #1
|
|
564
|
-
|
|
571
|
+
// Allow more characters after the first so we don't get faked
|
|
572
|
+
// out by certain schemes browsers accept
|
|
573
|
+
const matches = href.match(/^([a-zA-Z][a-zA-Z0-9.\-+]*):/);
|
|
565
574
|
if (!matches) {
|
|
566
575
|
// Protocol-relative URL starting with any combination of '/' and '\'
|
|
567
576
|
if (href.match(/^[/\\]{2}/)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sanitize-html",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.3",
|
|
4
4
|
"description": "Clean up user-submitted HTML, preserving whitelisted elements and whitelisted attributes on a per-element basis",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"main": "index.js",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"deepmerge": "^4.2.2",
|
|
27
27
|
"escape-string-regexp": "^4.0.0",
|
|
28
|
-
"htmlparser2": "^
|
|
28
|
+
"htmlparser2": "^6.0.0",
|
|
29
29
|
"is-plain-object": "^5.0.0",
|
|
30
30
|
"klona": "^2.0.3",
|
|
31
31
|
"parse-srcset": "^1.0.2",
|