sanitize-html 1.22.1 → 1.23.0
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 +5 -0
- package/README.md +8 -6
- package/dist/sanitize-html-es2015.js +30 -26
- package/dist/sanitize-html.js +4 -3
- package/dist/sanitize-html.min.js +1 -1
- package/package.json +14 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
## Changelog
|
|
2
2
|
|
|
3
|
+
1.23.0:
|
|
4
|
+
- Adds eslint configuration and adds eslint to test script.
|
|
5
|
+
- Sets `sideEffects: false` on package.json to allow module bundlers like webpack tree-shake this module and all the dependencies from client build. Thanks to [Egor Voronov](https://github.com/egorvoronov) for the contribution.
|
|
6
|
+
- Adds the `tagName` (HTML element name) as a second parameter passed to `textFilter`. Thanks to [Slava](https://github.com/slavaGanzin) for the contribution.
|
|
7
|
+
|
|
3
8
|
1.22.1: Increases the patch version of `lodash.mergewith` to enforce an audit fix.
|
|
4
9
|
|
|
5
10
|
1.22.0: bumped `htmlparser2` dependency to the 4.x series. This fixes longstanding bugs and should cause no bc breaks for this module, since the only bc breaks upstream are in regard to features we don't expose in this module.
|
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# sanitize-html
|
|
2
2
|
|
|
3
|
-
[](https://circleci.com/gh/apostrophecms/sanitize-html/tree/master)
|
|
4
4
|
|
|
5
|
-
<a href="https://apostrophecms.
|
|
5
|
+
<a href="https://apostrophecms.com/"><img src="https://raw.github.com/apostrophecms/sanitize-html/master/logos/logo-box-madefor.png" align="right" /></a>
|
|
6
6
|
|
|
7
7
|
`sanitize-html` provides a simple HTML sanitizer with a clear API.
|
|
8
8
|
|
|
@@ -318,7 +318,9 @@ We can do that with the following filter:
|
|
|
318
318
|
sanitizeHtml(
|
|
319
319
|
'<p>some text...</p>',
|
|
320
320
|
{
|
|
321
|
-
textFilter: function(text) {
|
|
321
|
+
textFilter: function(text, tagName) {
|
|
322
|
+
if (['a'].indexOf(tagName) > -1) return //Skip anchor tags
|
|
323
|
+
|
|
322
324
|
return text.replace(/\.\.\./, '…');
|
|
323
325
|
}
|
|
324
326
|
}
|
|
@@ -515,10 +517,10 @@ Valid values are: `'discard'` (default), `'escape'` (escape the tag) and `'recur
|
|
|
515
517
|
|
|
516
518
|
## Changelog
|
|
517
519
|
|
|
518
|
-
[The changelog is now in a separate file for readability.](https://github.com/
|
|
520
|
+
[The changelog is now in a separate file for readability.](https://github.com/apostrophecms/sanitize-html/blob/master/CHANGELOG.md)
|
|
519
521
|
|
|
520
522
|
## Support
|
|
521
523
|
|
|
522
|
-
Feel free to open issues on [github](http://github.com/
|
|
524
|
+
Feel free to open issues on [github](http://github.com/apostrophecms/sanitize-html).
|
|
523
525
|
|
|
524
|
-
<a href="http://
|
|
526
|
+
<a href="http://apostrophecms.com/"><img src="https://raw.github.com/apostrophecms/sanitize-html/master/logos/logo-box-builtby.png" /></a>
|
|
@@ -20807,6 +20807,7 @@ function extend() {
|
|
|
20807
20807
|
}
|
|
20808
20808
|
|
|
20809
20809
|
},{}],83:[function(require,module,exports){
|
|
20810
|
+
/* eslint-disable no-useless-escape */
|
|
20810
20811
|
var htmlparser = require('htmlparser2');
|
|
20811
20812
|
var extend = require('xtend');
|
|
20812
20813
|
var quoteRegexp = require('lodash.escaperegexp');
|
|
@@ -20819,9 +20820,11 @@ var postcss = require('postcss');
|
|
|
20819
20820
|
var url = require('url');
|
|
20820
20821
|
|
|
20821
20822
|
function each(obj, cb) {
|
|
20822
|
-
if (obj)
|
|
20823
|
-
|
|
20824
|
-
|
|
20823
|
+
if (obj) {
|
|
20824
|
+
Object.keys(obj).forEach(function (key) {
|
|
20825
|
+
cb(obj[key], key);
|
|
20826
|
+
});
|
|
20827
|
+
}
|
|
20825
20828
|
}
|
|
20826
20829
|
|
|
20827
20830
|
// Avoid false positives with .__proto__, .hasOwnProperty, etc.
|
|
@@ -20841,7 +20844,7 @@ function filter(a, cb) {
|
|
|
20841
20844
|
}
|
|
20842
20845
|
|
|
20843
20846
|
function isEmptyObject(obj) {
|
|
20844
|
-
for(var key in obj) {
|
|
20847
|
+
for (var key in obj) {
|
|
20845
20848
|
if (has(obj, key)) {
|
|
20846
20849
|
return false;
|
|
20847
20850
|
}
|
|
@@ -20882,8 +20885,8 @@ function sanitizeHtml(html, options, _recursing) {
|
|
|
20882
20885
|
|
|
20883
20886
|
this.updateParentNodeText = function() {
|
|
20884
20887
|
if (stack.length) {
|
|
20885
|
-
|
|
20886
|
-
|
|
20888
|
+
var parentFrame = stack[stack.length - 1];
|
|
20889
|
+
parentFrame.text += that.text;
|
|
20887
20890
|
}
|
|
20888
20891
|
};
|
|
20889
20892
|
}
|
|
@@ -20907,14 +20910,14 @@ function sanitizeHtml(html, options, _recursing) {
|
|
|
20907
20910
|
var nonTextTagsArray = options.nonTextTags || [ 'script', 'style', 'textarea' ];
|
|
20908
20911
|
var allowedAttributesMap;
|
|
20909
20912
|
var allowedAttributesGlobMap;
|
|
20910
|
-
if(options.allowedAttributes) {
|
|
20913
|
+
if (options.allowedAttributes) {
|
|
20911
20914
|
allowedAttributesMap = {};
|
|
20912
20915
|
allowedAttributesGlobMap = {};
|
|
20913
20916
|
each(options.allowedAttributes, function(attributes, tag) {
|
|
20914
20917
|
allowedAttributesMap[tag] = [];
|
|
20915
20918
|
var globRegex = [];
|
|
20916
20919
|
attributes.forEach(function(obj) {
|
|
20917
|
-
if(isString(obj) && obj.indexOf('*') >= 0) {
|
|
20920
|
+
if (isString(obj) && obj.indexOf('*') >= 0) {
|
|
20918
20921
|
globRegex.push(quoteRegexp(obj).replace(/\\\*/g, '.*'));
|
|
20919
20922
|
} else {
|
|
20920
20923
|
allowedAttributesMap[tag].push(obj);
|
|
@@ -20926,14 +20929,14 @@ function sanitizeHtml(html, options, _recursing) {
|
|
|
20926
20929
|
var allowedClassesMap = {};
|
|
20927
20930
|
each(options.allowedClasses, function(classes, tag) {
|
|
20928
20931
|
// Implicitly allows the class attribute
|
|
20929
|
-
if(allowedAttributesMap) {
|
|
20932
|
+
if (allowedAttributesMap) {
|
|
20930
20933
|
if (!has(allowedAttributesMap, tag)) {
|
|
20931
20934
|
allowedAttributesMap[tag] = [];
|
|
20932
20935
|
}
|
|
20933
20936
|
allowedAttributesMap[tag].push('class');
|
|
20934
20937
|
}
|
|
20935
20938
|
|
|
20936
|
-
allowedClassesMap[tag] = classes
|
|
20939
|
+
allowedClassesMap[tag] = classes;
|
|
20937
20940
|
});
|
|
20938
20941
|
|
|
20939
20942
|
var transformTagsMap = {};
|
|
@@ -20969,7 +20972,7 @@ function sanitizeHtml(html, options, _recursing) {
|
|
|
20969
20972
|
stack.push(frame);
|
|
20970
20973
|
|
|
20971
20974
|
var skip = false;
|
|
20972
|
-
var hasText = frame.text
|
|
20975
|
+
var hasText = !!frame.text;
|
|
20973
20976
|
var transformedTag;
|
|
20974
20977
|
if (has(transformTagsMap, name)) {
|
|
20975
20978
|
transformedTag = transformTagsMap[name](name, attribs);
|
|
@@ -21029,11 +21032,11 @@ function sanitizeHtml(html, options, _recursing) {
|
|
|
21029
21032
|
// as necessary if there are specific values defined.
|
|
21030
21033
|
var passedAllowedAttributesMapCheck = false;
|
|
21031
21034
|
if (!allowedAttributesMap ||
|
|
21032
|
-
(has(allowedAttributesMap, name) && allowedAttributesMap[name].indexOf(a) !== -1
|
|
21033
|
-
(allowedAttributesMap['*'] && allowedAttributesMap['*'].indexOf(a) !== -1
|
|
21035
|
+
(has(allowedAttributesMap, name) && allowedAttributesMap[name].indexOf(a) !== -1) ||
|
|
21036
|
+
(allowedAttributesMap['*'] && allowedAttributesMap['*'].indexOf(a) !== -1) ||
|
|
21034
21037
|
(has(allowedAttributesGlobMap, name) && allowedAttributesGlobMap[name].test(a)) ||
|
|
21035
21038
|
(allowedAttributesGlobMap['*'] && allowedAttributesGlobMap['*'].test(a))) {
|
|
21036
|
-
|
|
21039
|
+
passedAllowedAttributesMapCheck = true;
|
|
21037
21040
|
} else if (allowedAttributesMap && allowedAttributesMap[name]) {
|
|
21038
21041
|
for (const o of allowedAttributesMap[name]) {
|
|
21039
21042
|
if (isPlainObject(o) && o.name && (o.name === a)) {
|
|
@@ -21075,8 +21078,8 @@ function sanitizeHtml(html, options, _recursing) {
|
|
|
21075
21078
|
var isRelativeUrl = parsed && parsed.host === null && parsed.protocol === null;
|
|
21076
21079
|
if (isRelativeUrl) {
|
|
21077
21080
|
// default value of allowIframeRelativeUrls is true unless allowIframeHostnames specified
|
|
21078
|
-
allowed = has(options, "allowIframeRelativeUrls")
|
|
21079
|
-
options.allowIframeRelativeUrls : !options.allowedIframeHostnames;
|
|
21081
|
+
allowed = has(options, "allowIframeRelativeUrls")
|
|
21082
|
+
? options.allowIframeRelativeUrls : !options.allowedIframeHostnames;
|
|
21080
21083
|
} else if (options.allowedIframeHostnames) {
|
|
21081
21084
|
allowed = options.allowedIframeHostnames.find(function (hostname) {
|
|
21082
21085
|
return hostname === parsed.hostname;
|
|
@@ -21131,7 +21134,7 @@ function sanitizeHtml(html, options, _recursing) {
|
|
|
21131
21134
|
|
|
21132
21135
|
value = stringifyStyleAttributes(filteredAST);
|
|
21133
21136
|
|
|
21134
|
-
if(value.length === 0) {
|
|
21137
|
+
if (value.length === 0) {
|
|
21135
21138
|
delete frame.attribs[a];
|
|
21136
21139
|
return;
|
|
21137
21140
|
}
|
|
@@ -21166,7 +21169,7 @@ function sanitizeHtml(html, options, _recursing) {
|
|
|
21166
21169
|
if (skipText) {
|
|
21167
21170
|
return;
|
|
21168
21171
|
}
|
|
21169
|
-
var lastFrame = stack[stack.length-1];
|
|
21172
|
+
var lastFrame = stack[stack.length - 1];
|
|
21170
21173
|
var tag;
|
|
21171
21174
|
|
|
21172
21175
|
if (lastFrame) {
|
|
@@ -21184,14 +21187,14 @@ function sanitizeHtml(html, options, _recursing) {
|
|
|
21184
21187
|
} else {
|
|
21185
21188
|
var escaped = escapeHtml(text, false);
|
|
21186
21189
|
if (options.textFilter) {
|
|
21187
|
-
result += options.textFilter(escaped);
|
|
21190
|
+
result += options.textFilter(escaped, tag);
|
|
21188
21191
|
} else {
|
|
21189
21192
|
result += escaped;
|
|
21190
21193
|
}
|
|
21191
21194
|
}
|
|
21192
21195
|
if (stack.length) {
|
|
21193
|
-
|
|
21194
|
-
|
|
21196
|
+
var frame = stack[stack.length - 1];
|
|
21197
|
+
frame.text += text;
|
|
21195
21198
|
}
|
|
21196
21199
|
},
|
|
21197
21200
|
onclosetag: function(name) {
|
|
@@ -21229,15 +21232,15 @@ function sanitizeHtml(html, options, _recursing) {
|
|
|
21229
21232
|
}
|
|
21230
21233
|
|
|
21231
21234
|
if (options.exclusiveFilter && options.exclusiveFilter(frame)) {
|
|
21232
|
-
|
|
21233
|
-
|
|
21235
|
+
result = result.substr(0, frame.tagPosition);
|
|
21236
|
+
return;
|
|
21234
21237
|
}
|
|
21235
21238
|
|
|
21236
21239
|
frame.updateParentNodeText();
|
|
21237
21240
|
|
|
21238
21241
|
if (options.selfClosing.indexOf(name) !== -1) {
|
|
21239
|
-
|
|
21240
|
-
|
|
21242
|
+
// Already output />
|
|
21243
|
+
return;
|
|
21241
21244
|
}
|
|
21242
21245
|
|
|
21243
21246
|
result += "</" + name + ">";
|
|
@@ -21253,7 +21256,7 @@ function sanitizeHtml(html, options, _recursing) {
|
|
|
21253
21256
|
return result;
|
|
21254
21257
|
|
|
21255
21258
|
function escapeHtml(s, quote) {
|
|
21256
|
-
if (typeof(s) !== 'string') {
|
|
21259
|
+
if (typeof (s) !== 'string') {
|
|
21257
21260
|
s = s + '';
|
|
21258
21261
|
}
|
|
21259
21262
|
if (options.parser.decodeEntities) {
|
|
@@ -21280,6 +21283,7 @@ function sanitizeHtml(html, options, _recursing) {
|
|
|
21280
21283
|
// Browsers ignore character codes of 32 (space) and below in a surprising
|
|
21281
21284
|
// number of situations. Start reading here:
|
|
21282
21285
|
// https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Embedded_tab
|
|
21286
|
+
// eslint-disable-next-line no-control-regex
|
|
21283
21287
|
href = href.replace(/[\x00-\x20]+/g, '');
|
|
21284
21288
|
// Clobber any comments in URLs, which the browser might
|
|
21285
21289
|
// interpret inside an XML data island, allowing
|
package/dist/sanitize-html.js
CHANGED
|
@@ -5557,7 +5557,7 @@ if(psychotic){result.hostname=result.host=isAbsolute?'':srcPath.length?srcPath.s
|
|
|
5557
5557
|
//this especially happens in cases like
|
|
5558
5558
|
//url.resolveObject('mailto:local1@domain1', 'local2@domain2')
|
|
5559
5559
|
var authInHost=result.host&&result.host.indexOf('@')>0?result.host.split('@'):false;if(authInHost){result.auth=authInHost.shift();result.host=result.hostname=authInHost.shift();}}mustEndAbs=mustEndAbs||result.host&&srcPath.length;if(mustEndAbs&&!isAbsolute){srcPath.unshift('');}if(!srcPath.length){result.pathname=null;result.path=null;}else{result.pathname=srcPath.join('/');}//to support request.http
|
|
5560
|
-
if(!util.isNull(result.pathname)||!util.isNull(result.search)){result.path=(result.pathname?result.pathname:'')+(result.search?result.search:'');}result.auth=relative.auth||result.auth;result.slashes=result.slashes||relative.slashes;result.href=result.format();return result;};Url.prototype.parseHost=function(){var host=this.host;var port=portPattern.exec(host);if(port){port=port[0];if(port!==':'){this.port=port.substr(1);}host=host.substr(0,host.length-port.length);}if(host)this.hostname=host;};},{"./util":81,"punycode":64,"querystring":67}],81:[function(require,module,exports){'use strict';module.exports={isString:function isString(arg){return typeof arg==='string';},isObject:function isObject(arg){return _typeof(arg)==='object'&&arg!==null;},isNull:function isNull(arg){return arg===null;},isNullOrUndefined:function isNullOrUndefined(arg){return arg==null;}};},{}],82:[function(require,module,exports){module.exports=extend;var hasOwnProperty=Object.prototype.hasOwnProperty;function extend(){var target={};for(var i=0;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;}},{}],83:[function(require,module,exports){var htmlparser=require('htmlparser2');var extend=require('xtend');var quoteRegexp=require('lodash.escaperegexp');var cloneDeep=require('lodash.clonedeep');var mergeWith=require('lodash.mergewith');var isString=require('lodash.isstring');var isPlainObject=require('lodash.isplainobject');var srcset=require('srcset');var postcss=require('postcss');var url=require('url');function each(obj,cb){if(obj)Object.keys(obj).forEach(function(key){cb(obj[key],key);});}// Avoid false positives with .__proto__, .hasOwnProperty, etc.
|
|
5560
|
+
if(!util.isNull(result.pathname)||!util.isNull(result.search)){result.path=(result.pathname?result.pathname:'')+(result.search?result.search:'');}result.auth=relative.auth||result.auth;result.slashes=result.slashes||relative.slashes;result.href=result.format();return result;};Url.prototype.parseHost=function(){var host=this.host;var port=portPattern.exec(host);if(port){port=port[0];if(port!==':'){this.port=port.substr(1);}host=host.substr(0,host.length-port.length);}if(host)this.hostname=host;};},{"./util":81,"punycode":64,"querystring":67}],81:[function(require,module,exports){'use strict';module.exports={isString:function isString(arg){return typeof arg==='string';},isObject:function isObject(arg){return _typeof(arg)==='object'&&arg!==null;},isNull:function isNull(arg){return arg===null;},isNullOrUndefined:function isNullOrUndefined(arg){return arg==null;}};},{}],82:[function(require,module,exports){module.exports=extend;var hasOwnProperty=Object.prototype.hasOwnProperty;function extend(){var target={};for(var i=0;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;}},{}],83:[function(require,module,exports){/* eslint-disable no-useless-escape */var htmlparser=require('htmlparser2');var extend=require('xtend');var quoteRegexp=require('lodash.escaperegexp');var cloneDeep=require('lodash.clonedeep');var mergeWith=require('lodash.mergewith');var isString=require('lodash.isstring');var isPlainObject=require('lodash.isplainobject');var srcset=require('srcset');var postcss=require('postcss');var url=require('url');function each(obj,cb){if(obj){Object.keys(obj).forEach(function(key){cb(obj[key],key);});}}// Avoid false positives with .__proto__, .hasOwnProperty, etc.
|
|
5561
5561
|
function has(obj,key){return{}.hasOwnProperty.call(obj,key);}// Returns those elements of `a` for which `cb(a)` returns truthy
|
|
5562
5562
|
function filter(a,cb){var n=[];each(a,function(v){if(cb(v)){n.push(v);}});return n;}function isEmptyObject(obj){for(var key in obj){if(has(obj,key)){return false;}}return true;}module.exports=sanitizeHtml;// A valid attribute name.
|
|
5563
5563
|
// We use a tolerant definition based on the set of strings defined by
|
|
@@ -5580,7 +5580,7 @@ this.updateParentNodeText=function(){if(stack.length){var parentFrame=stack[stac
|
|
|
5580
5580
|
// If we are not allowing these tags, we should drop their content too.
|
|
5581
5581
|
// For other tags you would drop the tag but keep its content.
|
|
5582
5582
|
var nonTextTagsArray=options.nonTextTags||['script','style','textarea'];var allowedAttributesMap;var allowedAttributesGlobMap;if(options.allowedAttributes){allowedAttributesMap={};allowedAttributesGlobMap={};each(options.allowedAttributes,function(attributes,tag){allowedAttributesMap[tag]=[];var globRegex=[];attributes.forEach(function(obj){if(isString(obj)&&obj.indexOf('*')>=0){globRegex.push(quoteRegexp(obj).replace(/\\\*/g,'.*'));}else{allowedAttributesMap[tag].push(obj);}});allowedAttributesGlobMap[tag]=new RegExp('^('+globRegex.join('|')+')$');});}var allowedClassesMap={};each(options.allowedClasses,function(classes,tag){// Implicitly allows the class attribute
|
|
5583
|
-
if(allowedAttributesMap){if(!has(allowedAttributesMap,tag)){allowedAttributesMap[tag]=[];}allowedAttributesMap[tag].push('class');}allowedClassesMap[tag]=classes;});var transformTagsMap={};var transformTagsAll;each(options.transformTags,function(transform,tag){var transFun;if(typeof transform==='function'){transFun=transform;}else if(typeof transform==="string"){transFun=sanitizeHtml.simpleTransform(transform);}if(tag==='*'){transformTagsAll=transFun;}else{transformTagsMap[tag]=transFun;}});var depth=0;var stack=[];var skipMap={};var transformMap={};var skipText=false;var skipTextDepth=0;var parser=new htmlparser.Parser({onopentag:function onopentag(name,attribs){if(skipText){skipTextDepth++;return;}var frame=new Frame(name,attribs);stack.push(frame);var skip=false;var hasText
|
|
5583
|
+
if(allowedAttributesMap){if(!has(allowedAttributesMap,tag)){allowedAttributesMap[tag]=[];}allowedAttributesMap[tag].push('class');}allowedClassesMap[tag]=classes;});var transformTagsMap={};var transformTagsAll;each(options.transformTags,function(transform,tag){var transFun;if(typeof transform==='function'){transFun=transform;}else if(typeof transform==="string"){transFun=sanitizeHtml.simpleTransform(transform);}if(tag==='*'){transformTagsAll=transFun;}else{transformTagsMap[tag]=transFun;}});var depth=0;var stack=[];var skipMap={};var transformMap={};var skipText=false;var skipTextDepth=0;var parser=new htmlparser.Parser({onopentag:function onopentag(name,attribs){if(skipText){skipTextDepth++;return;}var frame=new Frame(name,attribs);stack.push(frame);var skip=false;var hasText=!!frame.text;var transformedTag;if(has(transformTagsMap,name)){transformedTag=transformTagsMap[name](name,attribs);frame.attribs=attribs=transformedTag.attribs;if(transformedTag.text!==undefined){frame.innerText=transformedTag.text;}if(name!==transformedTag.tagName){frame.name=name=transformedTag.tagName;transformMap[depth]=transformedTag.tagName;}}if(transformTagsAll){transformedTag=transformTagsAll(name,attribs);frame.attribs=attribs=transformedTag.attribs;if(name!==transformedTag.tagName){frame.name=name=transformedTag.tagName;transformMap[depth]=transformedTag.tagName;}}if(options.allowedTags&&options.allowedTags.indexOf(name)===-1||options.disallowedTagsMode==='recursiveEscape'&&!isEmptyObject(skipMap)){skip=true;skipMap[depth]=true;if(options.disallowedTagsMode==='discard'){if(nonTextTagsArray.indexOf(name)!==-1){skipText=true;skipTextDepth=1;}}skipMap[depth]=true;}depth++;if(skip){if(options.disallowedTagsMode==='discard'){// We want the contents but not this tag
|
|
5584
5584
|
return;}tempResult=result;result='';}result+='<'+name;if(!allowedAttributesMap||has(allowedAttributesMap,name)||allowedAttributesMap['*']){each(attribs,function(value,a){if(!VALID_HTML_ATTRIBUTE_NAME.test(a)){// This prevents part of an attribute name in the output from being
|
|
5585
5585
|
// interpreted as the end of an attribute, or end of a tag.
|
|
5586
5586
|
delete frame.attribs[a];return;}var parsed;// check allowedAttributesMap for the element and attribute and modify the value
|
|
@@ -5597,7 +5597,7 @@ text=lastFrame.innerText!==undefined?lastFrame.innerText:text;}if(options.disall
|
|
|
5597
5597
|
// script tags is, by definition, game over for XSS protection, so if that's
|
|
5598
5598
|
// your concern, don't allow them. The same is essentially true for style tags
|
|
5599
5599
|
// which have their own collection of XSS vectors.
|
|
5600
|
-
result+=text;}else{var escaped=escapeHtml(text,false);if(options.textFilter){result+=options.textFilter(escaped);}else{result+=escaped;}}if(stack.length){var frame=stack[stack.length-1];frame.text+=text;}},onclosetag:function onclosetag(name){if(skipText){skipTextDepth--;if(!skipTextDepth){skipText=false;}else{return;}}var frame=stack.pop();if(!frame){// Do not crash on bad markup
|
|
5600
|
+
result+=text;}else{var escaped=escapeHtml(text,false);if(options.textFilter){result+=options.textFilter(escaped,tag);}else{result+=escaped;}}if(stack.length){var frame=stack[stack.length-1];frame.text+=text;}},onclosetag:function onclosetag(name){if(skipText){skipTextDepth--;if(!skipTextDepth){skipText=false;}else{return;}}var frame=stack.pop();if(!frame){// Do not crash on bad markup
|
|
5601
5601
|
return;}skipText=false;depth--;var skip=skipMap[depth];if(skip){delete skipMap[depth];if(options.disallowedTagsMode==='discard'){frame.updateParentNodeText();return;}tempResult=result;result='';}if(transformMap[depth]){name=transformMap[depth];delete transformMap[depth];}if(options.exclusiveFilter&&options.exclusiveFilter(frame)){result=result.substr(0,frame.tagPosition);return;}frame.updateParentNodeText();if(options.selfClosing.indexOf(name)!==-1){// Already output />
|
|
5602
5602
|
return;}result+="</"+name+">";if(skip){result=tempResult+escapeHtml(result);tempResult='';}}},options.parser);parser.write(html);parser.end();return result;function escapeHtml(s,quote){if(typeof s!=='string'){s=s+'';}if(options.parser.decodeEntities){s=s.replace(/&/g,'&').replace(/</g,'<').replace(/\>/g,'>');if(quote){s=s.replace(/\"/g,'"');}}// TODO: this is inadequate because it will pass `&0;`. This approach
|
|
5603
5603
|
// will not work, each & must be considered with regard to whether it
|
|
@@ -5608,6 +5608,7 @@ s=s.replace(/&(?![a-zA-Z0-9#]{1,20};)/g,'&')// Match ampersands not part of
|
|
|
5608
5608
|
.replace(/</g,'<').replace(/\>/g,'>');if(quote){s=s.replace(/\"/g,'"');}return s;}function naughtyHref(name,href){// Browsers ignore character codes of 32 (space) and below in a surprising
|
|
5609
5609
|
// number of situations. Start reading here:
|
|
5610
5610
|
// https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Embedded_tab
|
|
5611
|
+
// eslint-disable-next-line no-control-regex
|
|
5611
5612
|
href=href.replace(/[\x00-\x20]+/g,'');// Clobber any comments in URLs, which the browser might
|
|
5612
5613
|
// interpret inside an XML data island, allowing
|
|
5613
5614
|
// a javascript: URL to be snuck through
|