sanitize-html
Advanced tools
Comparing version 1.16.3 to 1.17.0
@@ -10,2 +10,3 @@ 'use strict'; | ||
var postcss = require('postcss'); | ||
var url = require('url'); | ||
@@ -208,6 +209,28 @@ function each(obj, cb) { | ||
} | ||
if (name === 'iframe' && a === 'src') { | ||
//Check if value contains proper hostname prefix | ||
if (value.substring(0, 2) === '//') { | ||
var prefix = 'https:'; | ||
value = prefix.concat(value); | ||
} | ||
try { | ||
parsed = url.parse(value); | ||
if (options.allowedIframeHostnames) { | ||
var whitelistedHostnames = options.allowedIframeHostnames.find(function (hostname) { | ||
return hostname === parsed.hostname; | ||
}); | ||
if (!whitelistedHostnames) { | ||
delete frame.attribs[a]; | ||
return; | ||
} | ||
} | ||
} catch (e) { | ||
// Unparseable iframe src | ||
delete frame.attribs[a]; | ||
return; | ||
} | ||
} | ||
if (a === 'srcset') { | ||
try { | ||
var parsed = srcset.parse(value); | ||
parsed = srcset.parse(value); | ||
each(parsed, function (value) { | ||
@@ -236,3 +259,2 @@ if (naughtyHref('srcset', value.url)) { | ||
} | ||
if (a === 'class') { | ||
@@ -492,3 +514,3 @@ value = filterClasses(value, allowedClassesMap[name]); | ||
sanitizeHtml.defaults = { | ||
allowedTags: ['h3', 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', 'ol', 'nl', 'li', 'b', 'i', 'strong', 'em', 'strike', 'code', 'hr', 'br', 'div', 'table', 'thead', 'caption', 'tbody', 'tr', 'th', 'td', 'pre'], | ||
allowedTags: ['h3', 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', 'ol', 'nl', 'li', 'b', 'i', 'strong', 'em', 'strike', 'code', 'hr', 'br', 'div', 'table', 'thead', 'caption', 'tbody', 'tr', 'th', 'td', 'pre', 'iframe'], | ||
allowedAttributes: { | ||
@@ -495,0 +517,0 @@ a: ['href', 'name', 'target'], |
{ | ||
"name": "sanitize-html", | ||
"version": "1.16.3", | ||
"version": "1.17.0", | ||
"description": "Clean up user-submitted HTML, preserving whitelisted elements and whitelisted attributes on a per-element basis", | ||
@@ -28,2 +28,3 @@ "main": "dist/index.js", | ||
"dependencies": { | ||
"chalk": "^2.3.0", | ||
"htmlparser2": "^3.9.0", | ||
@@ -30,0 +31,0 @@ "lodash.clonedeep": "^4.5.0", |
@@ -17,2 +17,4 @@ # sanitize-html | ||
Allowing particular urls as a `src` to an iframe tag by filtering hostnames is also supported. | ||
HTML comments are not preserved. | ||
@@ -86,3 +88,4 @@ | ||
'a': [ 'href' ] | ||
} | ||
}, | ||
allowedIframeHostnames: ['www.youtube.com'] | ||
}); | ||
@@ -120,3 +123,4 @@ ``` | ||
allowedSchemesByTag: {}, | ||
allowProtocolRelative: true | ||
allowProtocolRelative: true, | ||
allowedIframeHostnames: ['www.youtube.com', 'player.vimeo.com'] | ||
``` | ||
@@ -300,2 +304,57 @@ | ||
### Iframe Filters | ||
If you would like to allow iframe tags but want to control the domains that are allowed through you can provide an array of hostnames that you would like to allow as iframe sources. This hostname is a property in the options object passed as an argument to the `sanitize-html` function. | ||
This array will be checked against the html that is passed to the function and return only `src` urls that include the allowed hostnames in the object. The url in the html that is passed must be formatted correctly (valid hostname) as an embedded iframe otherwise the module will strip out the src from the iframe. | ||
Make sure to pass a valid hostname along with the domain you wish to allow, i.e.: | ||
```javascript | ||
allowedIframeHostnames: ['www.youtube.com', 'player.vimeo.com'] | ||
``` | ||
**Remember that the `iframe` tag must be allowed as well as the `src` attribute.** | ||
For example: | ||
```javascript | ||
clean = sanitizeHtml('<p><iframe src="https://www.youtube.com/embed/nykIhs12345"></iframe><p>', { | ||
allowedTags: [ 'p', 'em', 'strong', 'iframe' ], | ||
allowedClasses: { | ||
'p': [ 'fancy', 'simple' ], | ||
'iframe': ['src'] | ||
}, | ||
allowedIframeHostnames: ['www.youtube.com', 'player.vimeo.com'] | ||
}); | ||
``` | ||
will pass through as safe whereas: | ||
```javascript | ||
clean = sanitizeHtml('<p><iframe src="https://www.youtube.net/embed/nykIhs12345"></iframe><p>', { | ||
allowedTags: [ 'p', 'em', 'strong', 'iframe' ], | ||
allowedClasses: { | ||
'p': [ 'fancy', 'simple' ], | ||
'iframe': ['src'] | ||
}, | ||
allowedIframeHostnames: ['www.youtube.com', 'player.vimeo.com'] | ||
}); | ||
``` | ||
or | ||
```javascript | ||
clean = sanitizeHtml('<p><iframe src="https://www.vimeo/video/12345"></iframe><p>', { | ||
allowedTags: [ 'p', 'em', 'strong', 'iframe' ], | ||
allowedClasses: { | ||
'p': [ 'fancy', 'simple' ], | ||
'iframe': ['src'] | ||
}, | ||
allowedIframeHostnames: ['www.youtube.com', 'player.vimeo.com'] | ||
}); | ||
``` | ||
will return an empty iframe tag. | ||
### Allowed CSS Classes | ||
@@ -404,2 +463,4 @@ | ||
1.17.0: the new `allowedIframeHostnames` option. If present, this must be an array, and only iframe `src` URLs hostnames (complete hostnames; domain name matches are not enough) that appear on this list are allowed. You must also configure `hostname` as an allowed attribute for `iframe`. Thanks to Ryan Verys for this contribution. | ||
1.16.3: don't throw away the browserified versions before publishing them. `prepare` is not a good place to `make clean`, it runs after `prepublish`. | ||
@@ -406,0 +467,0 @@ |
@@ -8,2 +8,3 @@ var htmlparser = require('htmlparser2'); | ||
var postcss = require('postcss'); | ||
var url = require('url'); | ||
@@ -210,6 +211,28 @@ function each(obj, cb) { | ||
} | ||
if (name === 'iframe' && a === 'src') { | ||
//Check if value contains proper hostname prefix | ||
if (value.substring(0, 2) === '//') { | ||
var prefix = 'https:'; | ||
value = prefix.concat(value); | ||
} | ||
try { | ||
parsed = url.parse(value); | ||
if (options.allowedIframeHostnames) { | ||
var whitelistedHostnames = options.allowedIframeHostnames.find(function(hostname) { | ||
return hostname === parsed.hostname; | ||
}); | ||
if (!whitelistedHostnames) { | ||
delete frame.attribs[a]; | ||
return; | ||
} | ||
} | ||
} catch (e) { | ||
// Unparseable iframe src | ||
delete frame.attribs[a]; | ||
return; | ||
} | ||
} | ||
if (a === 'srcset') { | ||
try { | ||
var parsed = srcset.parse(value); | ||
parsed = srcset.parse(value); | ||
each(parsed, function(value) { | ||
@@ -238,3 +261,2 @@ if (naughtyHref('srcset', value.url)) { | ||
} | ||
if (a === 'class') { | ||
@@ -504,3 +526,3 @@ value = filterClasses(value, allowedClassesMap[name]); | ||
'nl', 'li', 'b', 'i', 'strong', 'em', 'strike', 'code', 'hr', 'br', 'div', | ||
'table', 'thead', 'caption', 'tbody', 'tr', 'th', 'td', 'pre' ], | ||
'table', 'thead', 'caption', 'tbody', 'tr', 'th', 'td', 'pre', 'iframe' ], | ||
allowedAttributes: { | ||
@@ -507,0 +529,0 @@ a: [ 'href', 'name', 'target' ], |
@@ -650,2 +650,37 @@ var assert = require("assert"); | ||
}); | ||
it('Should allow only hostnames in an iframe that are whitelisted', function() { | ||
assert.equal( | ||
sanitizeHtml('<iframe src="https://www.youtube.com/embed/c2IlcS7AHxM"></iframe>', { | ||
allowedTags: ['p', 'iframe', 'a', 'img', 'i'], | ||
allowedAttributes: {'iframe': ['src', 'href'], 'a': ['src', 'href'], 'img': ['src']}, | ||
allowedIframeHostnames: ['www.youtube.com', 'player.vimeo.com'] | ||
}), '<iframe src="https://www.youtube.com/embed/c2IlcS7AHxM"></iframe>' | ||
); | ||
}); | ||
it('Should remove iframe src urls that are not inlcuded in whitelisted hostnames', function() { | ||
assert.equal( | ||
sanitizeHtml('<iframe src="https://www.embed.vevo.com/USUV71704255"></iframe>', { | ||
allowedTags: ['p', 'iframe', 'a', 'img', 'i'], | ||
allowedAttributes: {'iframe': ['src', 'href'], 'a': ['src', 'href'], 'img': ['src']}, | ||
allowedIframeHostnames: ['www.youtube.com', 'player.vimeo.com'] | ||
}), '<iframe></iframe>' | ||
); | ||
}); | ||
it('Should not allow iframe urls that do not have proper hostname', function() { | ||
assert.equal( | ||
sanitizeHtml('<iframe src="//www.vimeo.com/embed/c2IlcS7AHxM"></iframe>', { | ||
allowedTags: ['p', 'iframe', 'a', 'img', 'i'], | ||
allowedAttributes: {'iframe': ['src', 'href'], 'a': ['src', 'href'], 'img': ['src']}, | ||
allowedIframeHostnames: ['www.youtube.com', 'player.vimeo.com'] | ||
}), '<iframe></iframe>' | ||
); | ||
}); | ||
it('Should allow iframe through if no hostname option is set', function() { | ||
assert.equal( | ||
sanitizeHtml('<iframe src="https://www.vimeo.com/embed/c2IlcS7AHxM"></iframe>', { | ||
allowedTags: ['p', 'iframe', 'a', 'img', 'i'], | ||
allowedAttributes: {'iframe': ['src', 'href'], 'a': ['src', 'href'], 'img': ['src']} | ||
}), '<iframe src="https://www.vimeo.com/embed/c2IlcS7AHxM"></iframe>' | ||
); | ||
}); | ||
}); |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
1233735
24141
588
20
8
+ Addedchalk@^2.3.0