@deepmetier/xss 0.0.0-stage → 1.0.16
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/LICENSE +24 -0
- package/README.md +23 -2
- package/README.zh.md +24 -0
- package/bin/xss +67 -0
- package/dist/xss.js +1784 -0
- package/dist/xss.min.js +1 -0
- package/lib/cli.js +45 -0
- package/lib/default.js +468 -0
- package/lib/index.js +118 -0
- package/lib/parser.js +257 -0
- package/lib/util.js +34 -0
- package/lib/xss.js +237 -0
- package/package.json +63 -4
- package/typings/xss.d.ts +219 -0
package/dist/xss.min.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){var FilterCSS=require("cssfilter").FilterCSS;var getDefaultCSSWhiteList=require("cssfilter").getDefaultWhiteList;var _=require("./util");function getDefaultWhiteList(){return{a:["target","href","title"],abbr:["title"],address:[],area:["shape","coords","href","alt"],article:[],aside:[],audio:["autoplay","controls","crossorigin","loop","muted","preload","src"],b:[],bdi:["dir"],bdo:["dir"],big:[],blockquote:["cite"],br:[],caption:[],center:[],cite:[],code:[],col:["align","valign","span","width"],colgroup:["align","valign","span","width"],dd:[],del:["datetime"],details:["open"],div:[],dl:[],dt:[],em:[],figcaption:[],figure:[],font:["color","size","face"],footer:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],header:[],hr:[],i:[],img:["src","alt","title","width","height","loading"],ins:["datetime"],kbd:[],li:[],mark:[],nav:[],ol:[],p:[],pre:[],s:[],section:[],small:[],span:[],sub:[],summary:[],sup:[],strong:[],strike:[],table:["width","border","align","valign"],tbody:["align","valign"],td:["width","rowspan","colspan","align","valign"],tfoot:["align","valign"],th:["width","rowspan","colspan","align","valign"],thead:["align","valign"],tr:["rowspan","align","valign"],tt:[],u:[],ul:[],video:["autoplay","controls","crossorigin","loop","muted","playsinline","poster","preload","src","height","width"]}}var defaultCSSFilter=new FilterCSS;function onTag(tag,html,options){}function onIgnoreTag(tag,html,options){}function onTagAttr(tag,name,value){}function onIgnoreTagAttr(tag,name,value){}function escapeHtml(html){return html.replace(REGEXP_LT,"<").replace(REGEXP_GT,">")}function safeAttrValue(tag,name,value,cssFilter){value=friendlyAttrValue(value);if(name==="href"||name==="src"){value=_.trim(value);if(value==="#")return"#";if(!(value.substr(0,7)==="http://"||value.substr(0,8)==="https://"||value.substr(0,7)==="mailto:"||value.substr(0,4)==="tel:"||value.substr(0,11)==="data:image/"||value.substr(0,6)==="ftp://"||value.substr(0,2)==="./"||value.substr(0,3)==="../"||value[0]==="#"||value[0]==="/")){return""}}else if(name==="action"||name==="formaction"){value=_.trim(value);if(!/^https?:\/\//i.test(value)&&/^[^/?#]*:/.test(value)){return""}}else if(name==="background"){REGEXP_DEFAULT_ON_TAG_ATTR_4.lastIndex=0;if(REGEXP_DEFAULT_ON_TAG_ATTR_4.test(value)){return""}}else if(name==="style"){REGEXP_DEFAULT_ON_TAG_ATTR_7.lastIndex=0;if(REGEXP_DEFAULT_ON_TAG_ATTR_7.test(value)){return""}REGEXP_DEFAULT_ON_TAG_ATTR_8.lastIndex=0;if(REGEXP_DEFAULT_ON_TAG_ATTR_8.test(value)){REGEXP_DEFAULT_ON_TAG_ATTR_4.lastIndex=0;if(REGEXP_DEFAULT_ON_TAG_ATTR_4.test(value)){return""}}if(cssFilter!==false){cssFilter=cssFilter||defaultCSSFilter;value=cssFilter.process(value)}}value=escapeAttrValue(value);return value}var REGEXP_LT=/</g;var REGEXP_GT=/>/g;var REGEXP_QUOTE=/"/g;var REGEXP_QUOTE_2=/"/g;var REGEXP_ATTR_VALUE_1=/&#([a-zA-Z0-9]*);?/gim;var REGEXP_ATTR_VALUE_COLON=/:?/gim;var REGEXP_ATTR_VALUE_NEWLINE=/&newline;?/gim;var REGEXP_DEFAULT_ON_TAG_ATTR_4=/((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a):/gi;var REGEXP_DEFAULT_ON_TAG_ATTR_7=/e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/gi;var REGEXP_DEFAULT_ON_TAG_ATTR_8=/u\s*r\s*l\s*\(.*/gi;function escapeQuote(str){return str.replace(REGEXP_QUOTE,""")}function unescapeQuote(str){return str.replace(REGEXP_QUOTE_2,'"')}function escapeHtmlEntities(str){return str.replace(REGEXP_ATTR_VALUE_1,function replaceUnicode(str,code){return code[0]==="x"||code[0]==="X"?String.fromCharCode(parseInt(code.substr(1),16)):String.fromCharCode(parseInt(code,10))})}function escapeDangerHtml5Entities(str){return str.replace(REGEXP_ATTR_VALUE_COLON,":").replace(REGEXP_ATTR_VALUE_NEWLINE," ")}function clearNonPrintableCharacter(str){var str2="";for(var i=0,len=str.length;i<len;i++){str2+=str.charCodeAt(i)<32?" ":str.charAt(i)}return _.trim(str2)}function friendlyAttrValue(str){str=unescapeQuote(str);str=escapeHtmlEntities(str);str=escapeDangerHtml5Entities(str);str=clearNonPrintableCharacter(str);return str}function escapeAttrValue(str){str=escapeQuote(str);str=escapeHtml(str);return str}function onIgnoreTagStripAll(){return""}function StripTagBody(tags,next){if(typeof next!=="function"){next=function(){}}var isRemoveAllTag=!Array.isArray(tags);function isRemoveTag(tag){if(isRemoveAllTag)return true;return _.indexOf(tags,tag)!==-1}var removeList=[];var posStart=false;return{onIgnoreTag:function(tag,html,options){if(isRemoveTag(tag)){if(options.isClosing){var ret="[/removed]";var end=options.position+ret.length;removeList.push([posStart!==false?posStart:options.position,end]);posStart=false;return ret}else{if(!posStart){posStart=options.position}return"[removed]"}}else{return next(tag,html,options)}},remove:function(html){var rethtml="";var lastPos=0;_.forEach(removeList,function(pos){rethtml+=html.slice(lastPos,pos[0]);lastPos=pos[1]});rethtml+=html.slice(lastPos);return rethtml}}}function stripCommentTag(html){var retHtml="";var lastPos=0;while(lastPos<html.length){var i=html.indexOf("\x3c!--",lastPos);if(i===-1){retHtml+=html.slice(lastPos);break}retHtml+=html.slice(lastPos,i);var j=html.indexOf("--\x3e",i);if(j===-1){break}lastPos=j+3}return retHtml}function stripBlankChar(html){var chars=html.split("");chars=chars.filter(function(char){var c=char.charCodeAt(0);if(c===127)return false;if(c<=31){if(c===10||c===13)return true;return false}return true});return chars.join("")}exports.whiteList=getDefaultWhiteList();exports.getDefaultWhiteList=getDefaultWhiteList;exports.onTag=onTag;exports.onIgnoreTag=onIgnoreTag;exports.onTagAttr=onTagAttr;exports.onIgnoreTagAttr=onIgnoreTagAttr;exports.safeAttrValue=safeAttrValue;exports.escapeHtml=escapeHtml;exports.escapeQuote=escapeQuote;exports.unescapeQuote=unescapeQuote;exports.escapeHtmlEntities=escapeHtmlEntities;exports.escapeDangerHtml5Entities=escapeDangerHtml5Entities;exports.clearNonPrintableCharacter=clearNonPrintableCharacter;exports.friendlyAttrValue=friendlyAttrValue;exports.escapeAttrValue=escapeAttrValue;exports.onIgnoreTagStripAll=onIgnoreTagStripAll;exports.StripTagBody=StripTagBody;exports.stripCommentTag=stripCommentTag;exports.stripBlankChar=stripBlankChar;exports.attributeWrapSign='"';exports.cssFilter=defaultCSSFilter;exports.getDefaultCSSWhiteList=getDefaultCSSWhiteList},{"./util":4,cssfilter:8}],2:[function(require,module,exports){var DEFAULT=require("./default");var parser=require("./parser");var FilterXSS=require("./xss");function filterXSS(html,options){var xss=new FilterXSS(options);return xss.process(html)}function filterXSSWithResult(html,options){var removed=[];var opts={};if(options){for(var key in options){opts[key]=options[key]}}var originalOnIgnoreTag=opts.onIgnoreTag;var originalOnIgnoreTagAttr=opts.onIgnoreTagAttr;opts.onIgnoreTag=function(tag,tagHtml,tagOptions){removed.push({type:"tag",tag:tag,html:tagHtml,isClosing:!!(tagOptions&&tagOptions.isClosing)});if(originalOnIgnoreTag){return originalOnIgnoreTag(tag,tagHtml,tagOptions)}};opts.onIgnoreTagAttr=function(tag,name,value,isWhiteAttr){removed.push({type:"attr",tag:tag,attr:name,value:value});if(originalOnIgnoreTagAttr){return originalOnIgnoreTagAttr(tag,name,value,isWhiteAttr)}};var cleanHtml=filterXSS(html,opts);return{html:cleanHtml,removed:removed}}exports=module.exports=filterXSS;exports.filterXSS=filterXSS;exports.filterXSSWithResult=filterXSSWithResult;exports.FilterXSS=FilterXSS;(function(){for(var i in DEFAULT){if(Object.prototype.hasOwnProperty.call(DEFAULT,i)){exports[i]=DEFAULT[i]}}for(var j in parser){if(Object.prototype.hasOwnProperty.call(parser,j)){exports[j]=parser[j]}}})();if(typeof window!=="undefined"){window.filterXSS=module.exports}function isWorkerEnv(){return typeof self!=="undefined"&&typeof DedicatedWorkerGlobalScope!=="undefined"&&self instanceof DedicatedWorkerGlobalScope}if(isWorkerEnv()){self.filterXSS=module.exports}},{"./default":1,"./parser":3,"./xss":5}],3:[function(require,module,exports){var _=require("./util");function getTagName(html){var i=_.spaceIndex(html);var tagName;if(i===-1){tagName=html.slice(1,-1)}else{tagName=html.slice(1,i+1)}tagName=_.trim(tagName).toLowerCase();if(tagName.slice(0,1)==="/")tagName=tagName.slice(1);if(tagName.slice(-1)==="/")tagName=tagName.slice(0,-1);return tagName}function isClosing(html){return html.slice(0,2)==="</"}function parseTag(html,onTag,escapeHtml){"use strict";var rethtml="";var lastPos=0;var tagStart=false;var quoteStart=false;var currentPos=0;var len=html.length;var currentTagName="";var currentHtml="";chariterator:for(currentPos=0;currentPos<len;currentPos++){var c=html.charAt(currentPos);if(tagStart===false){if(c==="<"){tagStart=currentPos;continue}}else{if(quoteStart===false){if(c==="<"){rethtml+=escapeHtml(html.slice(lastPos,currentPos));tagStart=currentPos;lastPos=currentPos;continue}if(c===">"||currentPos===len-1){rethtml+=escapeHtml(html.slice(lastPos,tagStart));currentHtml=html.slice(tagStart,currentPos+1);currentTagName=getTagName(currentHtml);rethtml+=onTag(tagStart,rethtml.length,currentTagName,currentHtml,isClosing(currentHtml));lastPos=currentPos+1;tagStart=false;continue}if(c==='"'||c==="'"){var i=1;var ic=html.charAt(currentPos-i);while(ic.trim()===""||ic==="="){if(ic==="="){quoteStart=c;continue chariterator}ic=html.charAt(currentPos-++i)}}}else{if(c===quoteStart){quoteStart=false;continue}}}}if(lastPos<len){rethtml+=escapeHtml(html.substr(lastPos))}return rethtml}var REGEXP_ILLEGAL_ATTR_NAME=/[^a-zA-Z0-9\\_:.-]/gim;function parseAttr(html,onAttr){"use strict";var lastPos=0;var lastMarkPos=0;var retAttrs=[];var tmpName=false;var len=html.length;function addAttr(name,value){name=_.trim(name);name=name.replace(REGEXP_ILLEGAL_ATTR_NAME,"").toLowerCase();if(name.length<1)return;var ret=onAttr(name,value||"");if(ret)retAttrs.push(ret)}for(var i=0;i<len;i++){var c=html.charAt(i);var v,j;if(tmpName===false&&c==="="){tmpName=html.slice(lastPos,i);lastPos=i+1;lastMarkPos=html.charAt(lastPos)==='"'||html.charAt(lastPos)==="'"?lastPos:findNextQuotationMark(html,i+1);continue}if(tmpName!==false){if(i===lastMarkPos){j=html.indexOf(c,i+1);if(j===-1){break}else{v=_.trim(html.slice(lastMarkPos+1,j));addAttr(tmpName,v);tmpName=false;i=j;lastPos=i+1;continue}}}if(/\s|\n|\t/.test(c)){html=html.replace(/\s|\n|\t/g," ");if(tmpName===false){j=findNextEqual(html,i);if(j===-1){v=_.trim(html.slice(lastPos,i));addAttr(v);tmpName=false;lastPos=i+1;continue}else{i=j-1;continue}}else{j=findBeforeEqual(html,i-1);if(j===-1){v=_.trim(html.slice(lastPos,i));v=stripQuoteWrap(v);addAttr(tmpName,v);tmpName=false;lastPos=i+1;continue}else{continue}}}}if(lastPos<html.length){if(tmpName===false){addAttr(html.slice(lastPos))}else{addAttr(tmpName,stripQuoteWrap(_.trim(html.slice(lastPos))))}}return _.trim(retAttrs.join(" "))}function findNextEqual(str,i){for(;i<str.length;i++){var c=str[i];if(c===" ")continue;if(c==="=")return i;return-1}}function findNextQuotationMark(str,i){for(;i<str.length;i++){var c=str[i];if(c===" ")continue;if(c==="'"||c==='"')return i;return-1}}function findBeforeEqual(str,i){for(;i>0;i--){var c=str[i];if(c===" ")continue;if(c==="=")return i;return-1}}function isQuoteWrapString(text){if(text[0]==='"'&&text[text.length-1]==='"'||text[0]==="'"&&text[text.length-1]==="'"){return true}else{return false}}function stripQuoteWrap(text){if(isQuoteWrapString(text)){return text.substr(1,text.length-2)}else{return text}}exports.parseTag=parseTag;exports.parseAttr=parseAttr},{"./util":4}],4:[function(require,module,exports){module.exports={indexOf:function(arr,item){var i,j;if(Array.prototype.indexOf){return arr.indexOf(item)}for(i=0,j=arr.length;i<j;i++){if(arr[i]===item){return i}}return-1},forEach:function(arr,fn,scope){var i,j;if(Array.prototype.forEach){return arr.forEach(fn,scope)}for(i=0,j=arr.length;i<j;i++){fn.call(scope,arr[i],i,arr)}},trim:function(str){if(String.prototype.trim){return str.trim()}return str.replace(/(^\s*)|(\s*$)/g,"")},spaceIndex:function(str){var reg=/\s|\n|\t/;var match=reg.exec(str);return match?match.index:-1}}},{}],5:[function(require,module,exports){var FilterCSS=require("cssfilter").FilterCSS;var DEFAULT=require("./default");var parser=require("./parser");var parseTag=parser.parseTag;var parseAttr=parser.parseAttr;var _=require("./util");function isNull(obj){return obj===undefined||obj===null}function getAttrs(html){var i=_.spaceIndex(html);if(i===-1){return{html:"",closing:html[html.length-2]==="/"}}html=_.trim(html.slice(i+1,-1));var isClosing=html[html.length-1]==="/";if(isClosing)html=_.trim(html.slice(0,-1));return{html:html,closing:isClosing}}function shallowCopyObject(obj){var ret={};for(var i in obj){if(Object.prototype.hasOwnProperty.call(obj,i)){ret[i]=obj[i]}}return ret}function keysToLowerCase(obj){var ret={};for(var i in obj){if(Object.prototype.hasOwnProperty.call(obj,i)){if(Array.isArray(obj[i])){ret[i.toLowerCase()]=obj[i].map(function(item){return item.toLowerCase()})}else{ret[i.toLowerCase()]=obj[i]}}}return ret}function FilterXSS(options){options=shallowCopyObject(options||{});if(Object.prototype.hasOwnProperty.call(options,"stripIgnoreTag")&&options.stripIgnoreTag){if(Object.prototype.hasOwnProperty.call(options,"onIgnoreTag")&&options.onIgnoreTag){console.error('Notes: cannot use these two options "stripIgnoreTag" and "onIgnoreTag" at the same time')}options.onIgnoreTag=DEFAULT.onIgnoreTagStripAll}if(Object.prototype.hasOwnProperty.call(options,"whiteList")||Object.prototype.hasOwnProperty.call(options,"allowList")){const wl=Object.prototype.hasOwnProperty.call(options,"whiteList")?options.whiteList:options.allowList;options.whiteList=keysToLowerCase(wl)}else{options.whiteList=DEFAULT.whiteList}this.attributeWrapSign=Object.prototype.hasOwnProperty.call(options,"singleQuotedAttributeValue")&&options.singleQuotedAttributeValue===true?"'":DEFAULT.attributeWrapSign;options.onTag=Object.prototype.hasOwnProperty.call(options,"onTag")?options.onTag:DEFAULT.onTag;options.onTagAttr=Object.prototype.hasOwnProperty.call(options,"onTagAttr")?options.onTagAttr:DEFAULT.onTagAttr;options.onIgnoreTag=Object.prototype.hasOwnProperty.call(options,"onIgnoreTag")?options.onIgnoreTag:DEFAULT.onIgnoreTag;options.onIgnoreTagAttr=Object.prototype.hasOwnProperty.call(options,"onIgnoreTagAttr")?options.onIgnoreTagAttr:DEFAULT.onIgnoreTagAttr;options.safeAttrValue=Object.prototype.hasOwnProperty.call(options,"safeAttrValue")?options.safeAttrValue:DEFAULT.safeAttrValue;options.escapeHtml=Object.prototype.hasOwnProperty.call(options,"escapeHtml")?options.escapeHtml:DEFAULT.escapeHtml;this.options=options;if(Object.prototype.hasOwnProperty.call(options,"css")&&options.css===false){this.cssFilter=false}else{options.css=Object.prototype.hasOwnProperty.call(options,"css")?options.css:{};this.cssFilter=new FilterCSS(options.css)}}FilterXSS.prototype.process=function(html){html=html||"";html=html.toString();if(!html)return"";var me=this;var options=me.options;var whiteList=options.whiteList;var onTag=options.onTag;var onIgnoreTag=options.onIgnoreTag;var onTagAttr=options.onTagAttr;var onIgnoreTagAttr=options.onIgnoreTagAttr;var safeAttrValue=options.safeAttrValue;var escapeHtml=options.escapeHtml;var attributeWrapSign=me.attributeWrapSign;var cssFilter=me.cssFilter;if(options.stripBlankChar){html=DEFAULT.stripBlankChar(html)}if(!options.allowCommentTag){html=DEFAULT.stripCommentTag(html)}var stripIgnoreTagBody=false;if(options.stripIgnoreTagBody){stripIgnoreTagBody=DEFAULT.StripTagBody(options.stripIgnoreTagBody,onIgnoreTag);onIgnoreTag=stripIgnoreTagBody.onIgnoreTag}var retHtml=parseTag(html,function(sourcePosition,position,tag,html,isClosing){var info={sourcePosition:sourcePosition,position:position,isClosing:isClosing,isWhite:Object.prototype.hasOwnProperty.call(whiteList,tag)};var ret=onTag(tag,html,info);if(!isNull(ret))return ret;if(info.isWhite){if(info.isClosing){return"</"+tag+">"}var attrs=getAttrs(html);var whiteAttrList=whiteList[tag];var attrsHtml=parseAttr(attrs.html,function(name,value){var isWhiteAttr=_.indexOf(whiteAttrList,name)!==-1;var ret=onTagAttr(tag,name,value,isWhiteAttr);if(!isNull(ret))return ret;if(isWhiteAttr){value=safeAttrValue(tag,name,value,cssFilter);if(value){return name+"="+attributeWrapSign+value+attributeWrapSign}else{return name}}else{ret=onIgnoreTagAttr(tag,name,value,isWhiteAttr);if(!isNull(ret))return ret;return}});html="<"+tag;if(attrsHtml)html+=" "+attrsHtml;if(attrs.closing)html+=" /";html+=">";return html}else{ret=onIgnoreTag(tag,html,info);if(!isNull(ret))return ret;return escapeHtml(html)}},escapeHtml);if(stripIgnoreTagBody){retHtml=stripIgnoreTagBody.remove(retHtml)}return retHtml};module.exports=FilterXSS},{"./default":1,"./parser":3,"./util":4,cssfilter:8}],6:[function(require,module,exports){var DEFAULT=require("./default");var parseStyle=require("./parser");var _=require("./util");function isNull(obj){return obj===undefined||obj===null}function shallowCopyObject(obj){var ret={};for(var i in obj){ret[i]=obj[i]}return ret}function FilterCSS(options){options=shallowCopyObject(options||{});options.whiteList=options.whiteList||DEFAULT.whiteList;options.onAttr=options.onAttr||DEFAULT.onAttr;options.onIgnoreAttr=options.onIgnoreAttr||DEFAULT.onIgnoreAttr;options.safeAttrValue=options.safeAttrValue||DEFAULT.safeAttrValue;this.options=options}FilterCSS.prototype.process=function(css){css=css||"";css=css.toString();if(!css)return"";var me=this;var options=me.options;var whiteList=options.whiteList;var onAttr=options.onAttr;var onIgnoreAttr=options.onIgnoreAttr;var safeAttrValue=options.safeAttrValue;var retCSS=parseStyle(css,function(sourcePosition,position,name,value,source){var check=whiteList[name];var isWhite=false;if(check===true)isWhite=check;else if(typeof check==="function")isWhite=check(value);else if(check instanceof RegExp)isWhite=check.test(value);if(isWhite!==true)isWhite=false;value=safeAttrValue(name,value);if(!value)return;var opts={position:position,sourcePosition:sourcePosition,source:source,isWhite:isWhite};if(isWhite){var ret=onAttr(name,value,opts);if(isNull(ret)){return name+":"+value}else{return ret}}else{var ret=onIgnoreAttr(name,value,opts);if(!isNull(ret)){return ret}}});return retCSS};module.exports=FilterCSS},{"./default":7,"./parser":9,"./util":10}],7:[function(require,module,exports){function getDefaultWhiteList(){var whiteList={};whiteList["align-content"]=false;whiteList["align-items"]=false;whiteList["align-self"]=false;whiteList["alignment-adjust"]=false;whiteList["alignment-baseline"]=false;whiteList["all"]=false;whiteList["anchor-point"]=false;whiteList["animation"]=false;whiteList["animation-delay"]=false;whiteList["animation-direction"]=false;whiteList["animation-duration"]=false;whiteList["animation-fill-mode"]=false;whiteList["animation-iteration-count"]=false;whiteList["animation-name"]=false;whiteList["animation-play-state"]=false;whiteList["animation-timing-function"]=false;whiteList["azimuth"]=false;whiteList["backface-visibility"]=false;whiteList["background"]=true;whiteList["background-attachment"]=true;whiteList["background-clip"]=true;whiteList["background-color"]=true;whiteList["background-image"]=true;whiteList["background-origin"]=true;whiteList["background-position"]=true;whiteList["background-repeat"]=true;whiteList["background-size"]=true;whiteList["baseline-shift"]=false;whiteList["binding"]=false;whiteList["bleed"]=false;whiteList["bookmark-label"]=false;whiteList["bookmark-level"]=false;whiteList["bookmark-state"]=false;whiteList["border"]=true;whiteList["border-bottom"]=true;whiteList["border-bottom-color"]=true;whiteList["border-bottom-left-radius"]=true;whiteList["border-bottom-right-radius"]=true;whiteList["border-bottom-style"]=true;whiteList["border-bottom-width"]=true;whiteList["border-collapse"]=true;whiteList["border-color"]=true;whiteList["border-image"]=true;whiteList["border-image-outset"]=true;whiteList["border-image-repeat"]=true;whiteList["border-image-slice"]=true;whiteList["border-image-source"]=true;whiteList["border-image-width"]=true;whiteList["border-left"]=true;whiteList["border-left-color"]=true;whiteList["border-left-style"]=true;whiteList["border-left-width"]=true;whiteList["border-radius"]=true;whiteList["border-right"]=true;whiteList["border-right-color"]=true;whiteList["border-right-style"]=true;whiteList["border-right-width"]=true;whiteList["border-spacing"]=true;whiteList["border-style"]=true;whiteList["border-top"]=true;whiteList["border-top-color"]=true;whiteList["border-top-left-radius"]=true;whiteList["border-top-right-radius"]=true;whiteList["border-top-style"]=true;whiteList["border-top-width"]=true;whiteList["border-width"]=true;whiteList["bottom"]=false;whiteList["box-decoration-break"]=true;whiteList["box-shadow"]=true;whiteList["box-sizing"]=true;whiteList["box-snap"]=true;whiteList["box-suppress"]=true;whiteList["break-after"]=true;whiteList["break-before"]=true;whiteList["break-inside"]=true;whiteList["caption-side"]=false;whiteList["chains"]=false;whiteList["clear"]=true;whiteList["clip"]=false;whiteList["clip-path"]=false;whiteList["clip-rule"]=false;whiteList["color"]=true;whiteList["color-interpolation-filters"]=true;whiteList["column-count"]=false;whiteList["column-fill"]=false;whiteList["column-gap"]=false;whiteList["column-rule"]=false;whiteList["column-rule-color"]=false;whiteList["column-rule-style"]=false;whiteList["column-rule-width"]=false;whiteList["column-span"]=false;whiteList["column-width"]=false;whiteList["columns"]=false;whiteList["contain"]=false;whiteList["content"]=false;whiteList["counter-increment"]=false;whiteList["counter-reset"]=false;whiteList["counter-set"]=false;whiteList["crop"]=false;whiteList["cue"]=false;whiteList["cue-after"]=false;whiteList["cue-before"]=false;whiteList["cursor"]=false;whiteList["direction"]=false;whiteList["display"]=true;whiteList["display-inside"]=true;whiteList["display-list"]=true;whiteList["display-outside"]=true;whiteList["dominant-baseline"]=false;whiteList["elevation"]=false;whiteList["empty-cells"]=false;whiteList["filter"]=false;whiteList["flex"]=false;whiteList["flex-basis"]=false;whiteList["flex-direction"]=false;whiteList["flex-flow"]=false;whiteList["flex-grow"]=false;whiteList["flex-shrink"]=false;whiteList["flex-wrap"]=false;whiteList["float"]=false;whiteList["float-offset"]=false;whiteList["flood-color"]=false;whiteList["flood-opacity"]=false;whiteList["flow-from"]=false;whiteList["flow-into"]=false;whiteList["font"]=true;whiteList["font-family"]=true;whiteList["font-feature-settings"]=true;whiteList["font-kerning"]=true;whiteList["font-language-override"]=true;whiteList["font-size"]=true;whiteList["font-size-adjust"]=true;whiteList["font-stretch"]=true;whiteList["font-style"]=true;whiteList["font-synthesis"]=true;whiteList["font-variant"]=true;whiteList["font-variant-alternates"]=true;whiteList["font-variant-caps"]=true;whiteList["font-variant-east-asian"]=true;whiteList["font-variant-ligatures"]=true;whiteList["font-variant-numeric"]=true;whiteList["font-variant-position"]=true;whiteList["font-weight"]=true;whiteList["grid"]=false;whiteList["grid-area"]=false;whiteList["grid-auto-columns"]=false;whiteList["grid-auto-flow"]=false;whiteList["grid-auto-rows"]=false;whiteList["grid-column"]=false;whiteList["grid-column-end"]=false;whiteList["grid-column-start"]=false;whiteList["grid-row"]=false;whiteList["grid-row-end"]=false;whiteList["grid-row-start"]=false;whiteList["grid-template"]=false;whiteList["grid-template-areas"]=false;whiteList["grid-template-columns"]=false;whiteList["grid-template-rows"]=false;whiteList["hanging-punctuation"]=false;whiteList["height"]=true;whiteList["hyphens"]=false;whiteList["icon"]=false;whiteList["image-orientation"]=false;whiteList["image-resolution"]=false;whiteList["ime-mode"]=false;whiteList["initial-letters"]=false;whiteList["inline-box-align"]=false;whiteList["justify-content"]=false;whiteList["justify-items"]=false;whiteList["justify-self"]=false;whiteList["left"]=false;whiteList["letter-spacing"]=true;whiteList["lighting-color"]=true;whiteList["line-box-contain"]=false;whiteList["line-break"]=false;whiteList["line-grid"]=false;whiteList["line-height"]=false;whiteList["line-snap"]=false;whiteList["line-stacking"]=false;whiteList["line-stacking-ruby"]=false;whiteList["line-stacking-shift"]=false;whiteList["line-stacking-strategy"]=false;whiteList["list-style"]=true;whiteList["list-style-image"]=true;whiteList["list-style-position"]=true;whiteList["list-style-type"]=true;whiteList["margin"]=true;whiteList["margin-bottom"]=true;whiteList["margin-left"]=true;whiteList["margin-right"]=true;whiteList["margin-top"]=true;whiteList["marker-offset"]=false;whiteList["marker-side"]=false;whiteList["marks"]=false;whiteList["mask"]=false;whiteList["mask-box"]=false;whiteList["mask-box-outset"]=false;whiteList["mask-box-repeat"]=false;whiteList["mask-box-slice"]=false;whiteList["mask-box-source"]=false;whiteList["mask-box-width"]=false;whiteList["mask-clip"]=false;whiteList["mask-image"]=false;whiteList["mask-origin"]=false;whiteList["mask-position"]=false;whiteList["mask-repeat"]=false;whiteList["mask-size"]=false;whiteList["mask-source-type"]=false;whiteList["mask-type"]=false;whiteList["max-height"]=true;whiteList["max-lines"]=false;whiteList["max-width"]=true;whiteList["min-height"]=true;whiteList["min-width"]=true;whiteList["move-to"]=false;whiteList["nav-down"]=false;whiteList["nav-index"]=false;whiteList["nav-left"]=false;whiteList["nav-right"]=false;whiteList["nav-up"]=false;whiteList["object-fit"]=false;whiteList["object-position"]=false;whiteList["opacity"]=false;whiteList["order"]=false;whiteList["orphans"]=false;whiteList["outline"]=false;whiteList["outline-color"]=false;whiteList["outline-offset"]=false;whiteList["outline-style"]=false;whiteList["outline-width"]=false;whiteList["overflow"]=false;whiteList["overflow-wrap"]=false;whiteList["overflow-x"]=false;whiteList["overflow-y"]=false;whiteList["padding"]=true;whiteList["padding-bottom"]=true;whiteList["padding-left"]=true;whiteList["padding-right"]=true;whiteList["padding-top"]=true;whiteList["page"]=false;whiteList["page-break-after"]=false;whiteList["page-break-before"]=false;whiteList["page-break-inside"]=false;whiteList["page-policy"]=false;whiteList["pause"]=false;whiteList["pause-after"]=false;whiteList["pause-before"]=false;whiteList["perspective"]=false;whiteList["perspective-origin"]=false;whiteList["pitch"]=false;whiteList["pitch-range"]=false;whiteList["play-during"]=false;whiteList["position"]=false;whiteList["presentation-level"]=false;whiteList["quotes"]=false;whiteList["region-fragment"]=false;whiteList["resize"]=false;whiteList["rest"]=false;whiteList["rest-after"]=false;whiteList["rest-before"]=false;whiteList["richness"]=false;whiteList["right"]=false;whiteList["rotation"]=false;whiteList["rotation-point"]=false;whiteList["ruby-align"]=false;whiteList["ruby-merge"]=false;whiteList["ruby-position"]=false;whiteList["shape-image-threshold"]=false;whiteList["shape-outside"]=false;whiteList["shape-margin"]=false;whiteList["size"]=false;whiteList["speak"]=false;whiteList["speak-as"]=false;whiteList["speak-header"]=false;whiteList["speak-numeral"]=false;whiteList["speak-punctuation"]=false;whiteList["speech-rate"]=false;whiteList["stress"]=false;whiteList["string-set"]=false;whiteList["tab-size"]=false;whiteList["table-layout"]=false;whiteList["text-align"]=true;whiteList["text-align-last"]=true;whiteList["text-combine-upright"]=true;whiteList["text-decoration"]=true;whiteList["text-decoration-color"]=true;whiteList["text-decoration-line"]=true;whiteList["text-decoration-skip"]=true;whiteList["text-decoration-style"]=true;whiteList["text-emphasis"]=true;whiteList["text-emphasis-color"]=true;whiteList["text-emphasis-position"]=true;whiteList["text-emphasis-style"]=true;whiteList["text-height"]=true;whiteList["text-indent"]=true;whiteList["text-justify"]=true;whiteList["text-orientation"]=true;whiteList["text-overflow"]=true;whiteList["text-shadow"]=true;whiteList["text-space-collapse"]=true;whiteList["text-transform"]=true;whiteList["text-underline-position"]=true;whiteList["text-wrap"]=true;whiteList["top"]=false;whiteList["transform"]=false;whiteList["transform-origin"]=false;whiteList["transform-style"]=false;whiteList["transition"]=false;whiteList["transition-delay"]=false;whiteList["transition-duration"]=false;whiteList["transition-property"]=false;whiteList["transition-timing-function"]=false;whiteList["unicode-bidi"]=false;whiteList["vertical-align"]=false;whiteList["visibility"]=false;whiteList["voice-balance"]=false;whiteList["voice-duration"]=false;whiteList["voice-family"]=false;whiteList["voice-pitch"]=false;whiteList["voice-range"]=false;whiteList["voice-rate"]=false;whiteList["voice-stress"]=false;whiteList["voice-volume"]=false;whiteList["volume"]=false;whiteList["white-space"]=false;whiteList["widows"]=false;whiteList["width"]=true;whiteList["will-change"]=false;whiteList["word-break"]=true;whiteList["word-spacing"]=true;whiteList["word-wrap"]=true;whiteList["wrap-flow"]=false;whiteList["wrap-through"]=false;whiteList["writing-mode"]=false;whiteList["z-index"]=false;return whiteList}function onAttr(name,value,options){}function onIgnoreAttr(name,value,options){}var REGEXP_URL_JAVASCRIPT=/javascript\s*\:/gim;function safeAttrValue(name,value){if(REGEXP_URL_JAVASCRIPT.test(value))return"";return value}exports.whiteList=getDefaultWhiteList();exports.getDefaultWhiteList=getDefaultWhiteList;exports.onAttr=onAttr;exports.onIgnoreAttr=onIgnoreAttr;exports.safeAttrValue=safeAttrValue},{}],8:[function(require,module,exports){var DEFAULT=require("./default");var FilterCSS=require("./css");function filterCSS(html,options){var xss=new FilterCSS(options);return xss.process(html)}exports=module.exports=filterCSS;exports.FilterCSS=FilterCSS;for(var i in DEFAULT)exports[i]=DEFAULT[i];if(typeof window!=="undefined"){window.filterCSS=module.exports}},{"./css":6,"./default":7}],9:[function(require,module,exports){var _=require("./util");function parseStyle(css,onAttr){css=_.trimRight(css);if(css[css.length-1]!==";")css+=";";var cssLength=css.length;var isParenthesisOpen=false;var lastPos=0;var i=0;var retCSS="";function addNewAttr(){if(!isParenthesisOpen){var source=_.trim(css.slice(lastPos,i));var j=source.indexOf(":");if(j!==-1){var name=_.trim(source.slice(0,j));var value=_.trim(source.slice(j+1));if(name){var ret=onAttr(lastPos,retCSS.length,name,value,source);if(ret)retCSS+=ret+"; "}}}lastPos=i+1}for(;i<cssLength;i++){var c=css[i];if(c==="/"&&css[i+1]==="*"){var j=css.indexOf("*/",i+2);if(j===-1)break;i=j+1;lastPos=i+1;isParenthesisOpen=false}else if(c==="("){isParenthesisOpen=true}else if(c===")"){isParenthesisOpen=false}else if(c===";"){if(isParenthesisOpen){}else{addNewAttr()}}else if(c==="\n"){addNewAttr()}}return _.trim(retCSS)}module.exports=parseStyle},{"./util":10}],10:[function(require,module,exports){module.exports={indexOf:function(arr,item){var i,j;if(Array.prototype.indexOf){return arr.indexOf(item)}for(i=0,j=arr.length;i<j;i++){if(arr[i]===item){return i}}return-1},forEach:function(arr,fn,scope){var i,j;if(Array.prototype.forEach){return arr.forEach(fn,scope)}for(i=0,j=arr.length;i<j;i++){fn.call(scope,arr[i],i,arr)}},trim:function(str){if(String.prototype.trim){return str.trim()}return str.replace(/(^\s*)|(\s*$)/g,"")},trimRight:function(str){if(String.prototype.trimRight){return str.trimRight()}return str.replace(/(\s*$)/g,"")}}},{}]},{},[2]);
|
package/lib/cli.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* command line tool
|
|
3
|
+
*
|
|
4
|
+
* @author Zongmin Lei<leizongmin@gmail.com>
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
var xss = require("./");
|
|
8
|
+
var readline = require("readline");
|
|
9
|
+
|
|
10
|
+
var rl = readline.createInterface({
|
|
11
|
+
input: process.stdin,
|
|
12
|
+
output: process.stdout,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
console.log('Enter a blank line to do xss(), enter "@quit" to exit.\n');
|
|
16
|
+
|
|
17
|
+
function take(c, n) {
|
|
18
|
+
var ret = "";
|
|
19
|
+
for (var i = 0; i < n; i++) {
|
|
20
|
+
ret += c;
|
|
21
|
+
}
|
|
22
|
+
return ret;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function setPrompt(line) {
|
|
26
|
+
line = line.toString();
|
|
27
|
+
rl.setPrompt("[" + line + "]" + take(" ", 5 - line.length));
|
|
28
|
+
rl.prompt();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
setPrompt(1);
|
|
32
|
+
|
|
33
|
+
var html = [];
|
|
34
|
+
rl.on("line", function (line) {
|
|
35
|
+
if (line === "@quit") return process.exit();
|
|
36
|
+
if (line === "") {
|
|
37
|
+
console.log("");
|
|
38
|
+
console.log(xss(html.join("\r\n")));
|
|
39
|
+
console.log("");
|
|
40
|
+
html = [];
|
|
41
|
+
} else {
|
|
42
|
+
html.push(line);
|
|
43
|
+
}
|
|
44
|
+
setPrompt(html.length + 1);
|
|
45
|
+
});
|
package/lib/default.js
ADDED
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* default settings
|
|
3
|
+
*
|
|
4
|
+
* @author Zongmin Lei<leizongmin@gmail.com>
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
var FilterCSS = require("@deepmetier/cssfilter").FilterCSS;
|
|
8
|
+
var getDefaultCSSWhiteList = require("@deepmetier/cssfilter").getDefaultWhiteList;
|
|
9
|
+
var _ = require("./util");
|
|
10
|
+
|
|
11
|
+
function getDefaultWhiteList() {
|
|
12
|
+
return {
|
|
13
|
+
a: ["target", "href", "title"],
|
|
14
|
+
abbr: ["title"],
|
|
15
|
+
address: [],
|
|
16
|
+
area: ["shape", "coords", "href", "alt"],
|
|
17
|
+
article: [],
|
|
18
|
+
aside: [],
|
|
19
|
+
audio: [
|
|
20
|
+
"autoplay",
|
|
21
|
+
"controls",
|
|
22
|
+
"crossorigin",
|
|
23
|
+
"loop",
|
|
24
|
+
"muted",
|
|
25
|
+
"preload",
|
|
26
|
+
"src",
|
|
27
|
+
],
|
|
28
|
+
b: [],
|
|
29
|
+
bdi: ["dir"],
|
|
30
|
+
bdo: ["dir"],
|
|
31
|
+
big: [],
|
|
32
|
+
blockquote: ["cite"],
|
|
33
|
+
br: [],
|
|
34
|
+
caption: [],
|
|
35
|
+
center: [],
|
|
36
|
+
cite: [],
|
|
37
|
+
code: [],
|
|
38
|
+
col: ["align", "valign", "span", "width"],
|
|
39
|
+
colgroup: ["align", "valign", "span", "width"],
|
|
40
|
+
dd: [],
|
|
41
|
+
del: ["datetime"],
|
|
42
|
+
details: ["open"],
|
|
43
|
+
div: [],
|
|
44
|
+
dl: [],
|
|
45
|
+
dt: [],
|
|
46
|
+
em: [],
|
|
47
|
+
figcaption: [],
|
|
48
|
+
figure: [],
|
|
49
|
+
font: ["color", "size", "face"],
|
|
50
|
+
footer: [],
|
|
51
|
+
h1: [],
|
|
52
|
+
h2: [],
|
|
53
|
+
h3: [],
|
|
54
|
+
h4: [],
|
|
55
|
+
h5: [],
|
|
56
|
+
h6: [],
|
|
57
|
+
header: [],
|
|
58
|
+
hr: [],
|
|
59
|
+
i: [],
|
|
60
|
+
img: ["src", "alt", "title", "width", "height", "loading"],
|
|
61
|
+
ins: ["datetime"],
|
|
62
|
+
kbd: [],
|
|
63
|
+
li: [],
|
|
64
|
+
mark: [],
|
|
65
|
+
nav: [],
|
|
66
|
+
ol: [],
|
|
67
|
+
p: [],
|
|
68
|
+
pre: [],
|
|
69
|
+
s: [],
|
|
70
|
+
section: [],
|
|
71
|
+
small: [],
|
|
72
|
+
span: [],
|
|
73
|
+
sub: [],
|
|
74
|
+
summary: [],
|
|
75
|
+
sup: [],
|
|
76
|
+
strong: [],
|
|
77
|
+
strike: [],
|
|
78
|
+
table: ["width", "border", "align", "valign"],
|
|
79
|
+
tbody: ["align", "valign"],
|
|
80
|
+
td: ["width", "rowspan", "colspan", "align", "valign"],
|
|
81
|
+
tfoot: ["align", "valign"],
|
|
82
|
+
th: ["width", "rowspan", "colspan", "align", "valign"],
|
|
83
|
+
thead: ["align", "valign"],
|
|
84
|
+
tr: ["rowspan", "align", "valign"],
|
|
85
|
+
tt: [],
|
|
86
|
+
u: [],
|
|
87
|
+
ul: [],
|
|
88
|
+
video: [
|
|
89
|
+
"autoplay",
|
|
90
|
+
"controls",
|
|
91
|
+
"crossorigin",
|
|
92
|
+
"loop",
|
|
93
|
+
"muted",
|
|
94
|
+
"playsinline",
|
|
95
|
+
"poster",
|
|
96
|
+
"preload",
|
|
97
|
+
"src",
|
|
98
|
+
"height",
|
|
99
|
+
"width",
|
|
100
|
+
],
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
var defaultCSSFilter = new FilterCSS();
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* default onTag function
|
|
108
|
+
*
|
|
109
|
+
* @param {String} tag
|
|
110
|
+
* @param {String} html
|
|
111
|
+
* @param {Object} options
|
|
112
|
+
* @return {String}
|
|
113
|
+
*/
|
|
114
|
+
function onTag(tag, html, options) {
|
|
115
|
+
// do nothing
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* default onIgnoreTag function
|
|
120
|
+
*
|
|
121
|
+
* @param {String} tag
|
|
122
|
+
* @param {String} html
|
|
123
|
+
* @param {Object} options
|
|
124
|
+
* @return {String}
|
|
125
|
+
*/
|
|
126
|
+
function onIgnoreTag(tag, html, options) {
|
|
127
|
+
// do nothing
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* default onTagAttr function
|
|
132
|
+
*
|
|
133
|
+
* @param {String} tag
|
|
134
|
+
* @param {String} name
|
|
135
|
+
* @param {String} value
|
|
136
|
+
* @return {String}
|
|
137
|
+
*/
|
|
138
|
+
function onTagAttr(tag, name, value) {
|
|
139
|
+
// do nothing
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* default onIgnoreTagAttr function
|
|
144
|
+
*
|
|
145
|
+
* @param {String} tag
|
|
146
|
+
* @param {String} name
|
|
147
|
+
* @param {String} value
|
|
148
|
+
* @return {String}
|
|
149
|
+
*/
|
|
150
|
+
function onIgnoreTagAttr(tag, name, value) {
|
|
151
|
+
// do nothing
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* default escapeHtml function
|
|
156
|
+
*
|
|
157
|
+
* @param {String} html
|
|
158
|
+
*/
|
|
159
|
+
function escapeHtml(html) {
|
|
160
|
+
return html.replace(REGEXP_LT, "<").replace(REGEXP_GT, ">");
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* default safeAttrValue function
|
|
165
|
+
*
|
|
166
|
+
* @param {String} tag
|
|
167
|
+
* @param {String} name
|
|
168
|
+
* @param {String} value
|
|
169
|
+
* @param {Object} cssFilter
|
|
170
|
+
* @return {String}
|
|
171
|
+
*/
|
|
172
|
+
function safeAttrValue(tag, name, value, cssFilter) {
|
|
173
|
+
// unescape attribute value firstly
|
|
174
|
+
value = friendlyAttrValue(value);
|
|
175
|
+
|
|
176
|
+
if (name === "href" || name === "src") {
|
|
177
|
+
// filter `href` and `src` attribute
|
|
178
|
+
// only allow the value that starts with `http://` | `https://` | `mailto:` | `/` | `#`
|
|
179
|
+
value = _.trim(value);
|
|
180
|
+
if (value === "#") return "#";
|
|
181
|
+
if (
|
|
182
|
+
!(
|
|
183
|
+
value.substr(0, 7) === "http://" ||
|
|
184
|
+
value.substr(0, 8) === "https://" ||
|
|
185
|
+
value.substr(0, 7) === "mailto:" ||
|
|
186
|
+
value.substr(0, 4) === "tel:" ||
|
|
187
|
+
value.substr(0, 11) === "data:image/" ||
|
|
188
|
+
value.substr(0, 6) === "ftp://" ||
|
|
189
|
+
value.substr(0, 2) === "./" ||
|
|
190
|
+
value.substr(0, 3) === "../" ||
|
|
191
|
+
value[0] === "#" ||
|
|
192
|
+
value[0] === "/"
|
|
193
|
+
)
|
|
194
|
+
) {
|
|
195
|
+
return "";
|
|
196
|
+
}
|
|
197
|
+
} else if (name === "action" || name === "formaction") {
|
|
198
|
+
// Only allow HTTP(S) or relative form URLs; the href/src data:image/ exception does not apply.
|
|
199
|
+
// A relative URL's first segment cannot contain a colon; colons in queries and fragments are not schemes.
|
|
200
|
+
value = _.trim(value);
|
|
201
|
+
if (!/^https?:\/\//i.test(value) && /^[^/?#]*:/.test(value)) {
|
|
202
|
+
return "";
|
|
203
|
+
}
|
|
204
|
+
} else if (name === "background") {
|
|
205
|
+
// filter `background` attribute (maybe no use)
|
|
206
|
+
// `javascript:`
|
|
207
|
+
REGEXP_DEFAULT_ON_TAG_ATTR_4.lastIndex = 0;
|
|
208
|
+
if (REGEXP_DEFAULT_ON_TAG_ATTR_4.test(value)) {
|
|
209
|
+
return "";
|
|
210
|
+
}
|
|
211
|
+
} else if (name === "style") {
|
|
212
|
+
// `expression()`
|
|
213
|
+
REGEXP_DEFAULT_ON_TAG_ATTR_7.lastIndex = 0;
|
|
214
|
+
if (REGEXP_DEFAULT_ON_TAG_ATTR_7.test(value)) {
|
|
215
|
+
return "";
|
|
216
|
+
}
|
|
217
|
+
// `url()`
|
|
218
|
+
REGEXP_DEFAULT_ON_TAG_ATTR_8.lastIndex = 0;
|
|
219
|
+
if (REGEXP_DEFAULT_ON_TAG_ATTR_8.test(value)) {
|
|
220
|
+
REGEXP_DEFAULT_ON_TAG_ATTR_4.lastIndex = 0;
|
|
221
|
+
if (REGEXP_DEFAULT_ON_TAG_ATTR_4.test(value)) {
|
|
222
|
+
return "";
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
if (cssFilter !== false) {
|
|
226
|
+
cssFilter = cssFilter || defaultCSSFilter;
|
|
227
|
+
value = cssFilter.process(value);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// escape `<>"` before returns
|
|
232
|
+
value = escapeAttrValue(value);
|
|
233
|
+
return value;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// RegExp list
|
|
237
|
+
var REGEXP_LT = /</g;
|
|
238
|
+
var REGEXP_GT = />/g;
|
|
239
|
+
var REGEXP_QUOTE = /"/g;
|
|
240
|
+
var REGEXP_QUOTE_2 = /"/g;
|
|
241
|
+
var REGEXP_ATTR_VALUE_1 = /&#([a-zA-Z0-9]*);?/gim;
|
|
242
|
+
var REGEXP_ATTR_VALUE_COLON = /:?/gim;
|
|
243
|
+
var REGEXP_ATTR_VALUE_NEWLINE = /&newline;?/gim;
|
|
244
|
+
// var REGEXP_DEFAULT_ON_TAG_ATTR_3 = /\/\*|\*\//gm;
|
|
245
|
+
var REGEXP_DEFAULT_ON_TAG_ATTR_4 =
|
|
246
|
+
/((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a):/gi;
|
|
247
|
+
// var REGEXP_DEFAULT_ON_TAG_ATTR_5 = /^[\s"'`]*(d\s*a\s*t\s*a\s*)\:/gi;
|
|
248
|
+
// var REGEXP_DEFAULT_ON_TAG_ATTR_6 = /^[\s"'`]*(d\s*a\s*t\s*a\s*)\:\s*image\//gi;
|
|
249
|
+
var REGEXP_DEFAULT_ON_TAG_ATTR_7 =
|
|
250
|
+
/e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/gi;
|
|
251
|
+
var REGEXP_DEFAULT_ON_TAG_ATTR_8 = /u\s*r\s*l\s*\(.*/gi;
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* escape double quote
|
|
255
|
+
*
|
|
256
|
+
* @param {String} str
|
|
257
|
+
* @return {String} str
|
|
258
|
+
*/
|
|
259
|
+
function escapeQuote(str) {
|
|
260
|
+
return str.replace(REGEXP_QUOTE, """);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* unescape double quote
|
|
265
|
+
*
|
|
266
|
+
* @param {String} str
|
|
267
|
+
* @return {String} str
|
|
268
|
+
*/
|
|
269
|
+
function unescapeQuote(str) {
|
|
270
|
+
return str.replace(REGEXP_QUOTE_2, '"');
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* escape html entities
|
|
275
|
+
*
|
|
276
|
+
* @param {String} str
|
|
277
|
+
* @return {String}
|
|
278
|
+
*/
|
|
279
|
+
function escapeHtmlEntities(str) {
|
|
280
|
+
return str.replace(REGEXP_ATTR_VALUE_1, function replaceUnicode(str, code) {
|
|
281
|
+
return code[0] === "x" || code[0] === "X"
|
|
282
|
+
? String.fromCharCode(parseInt(code.substr(1), 16))
|
|
283
|
+
: String.fromCharCode(parseInt(code, 10));
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* escape html5 new danger entities
|
|
289
|
+
*
|
|
290
|
+
* @param {String} str
|
|
291
|
+
* @return {String}
|
|
292
|
+
*/
|
|
293
|
+
function escapeDangerHtml5Entities(str) {
|
|
294
|
+
return str
|
|
295
|
+
.replace(REGEXP_ATTR_VALUE_COLON, ":")
|
|
296
|
+
.replace(REGEXP_ATTR_VALUE_NEWLINE, " ");
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* clear nonprintable characters
|
|
301
|
+
*
|
|
302
|
+
* @param {String} str
|
|
303
|
+
* @return {String}
|
|
304
|
+
*/
|
|
305
|
+
function clearNonPrintableCharacter(str) {
|
|
306
|
+
var str2 = "";
|
|
307
|
+
for (var i = 0, len = str.length; i < len; i++) {
|
|
308
|
+
str2 += str.charCodeAt(i) < 32 ? " " : str.charAt(i);
|
|
309
|
+
}
|
|
310
|
+
return _.trim(str2);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* get friendly attribute value
|
|
315
|
+
*
|
|
316
|
+
* @param {String} str
|
|
317
|
+
* @return {String}
|
|
318
|
+
*/
|
|
319
|
+
function friendlyAttrValue(str) {
|
|
320
|
+
str = unescapeQuote(str);
|
|
321
|
+
str = escapeHtmlEntities(str);
|
|
322
|
+
str = escapeDangerHtml5Entities(str);
|
|
323
|
+
str = clearNonPrintableCharacter(str);
|
|
324
|
+
return str;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* unescape attribute value
|
|
329
|
+
*
|
|
330
|
+
* @param {String} str
|
|
331
|
+
* @return {String}
|
|
332
|
+
*/
|
|
333
|
+
function escapeAttrValue(str) {
|
|
334
|
+
str = escapeQuote(str);
|
|
335
|
+
str = escapeHtml(str);
|
|
336
|
+
return str;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* `onIgnoreTag` function for removing all the tags that are not in whitelist
|
|
341
|
+
*/
|
|
342
|
+
function onIgnoreTagStripAll() {
|
|
343
|
+
return "";
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* remove tag body
|
|
348
|
+
* specify a `tags` list, if the tag is not in the `tags` list then process by the specify function (optional)
|
|
349
|
+
*
|
|
350
|
+
* @param {array} tags
|
|
351
|
+
* @param {function} next
|
|
352
|
+
*/
|
|
353
|
+
function StripTagBody(tags, next) {
|
|
354
|
+
if (typeof next !== "function") {
|
|
355
|
+
next = function () {};
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
var isRemoveAllTag = !Array.isArray(tags);
|
|
359
|
+
function isRemoveTag(tag) {
|
|
360
|
+
if (isRemoveAllTag) return true;
|
|
361
|
+
return _.indexOf(tags, tag) !== -1;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
var removeList = [];
|
|
365
|
+
var posStart = false;
|
|
366
|
+
|
|
367
|
+
return {
|
|
368
|
+
onIgnoreTag: function (tag, html, options) {
|
|
369
|
+
if (isRemoveTag(tag)) {
|
|
370
|
+
if (options.isClosing) {
|
|
371
|
+
var ret = "[/removed]";
|
|
372
|
+
var end = options.position + ret.length;
|
|
373
|
+
removeList.push([
|
|
374
|
+
posStart !== false ? posStart : options.position,
|
|
375
|
+
end,
|
|
376
|
+
]);
|
|
377
|
+
posStart = false;
|
|
378
|
+
return ret;
|
|
379
|
+
} else {
|
|
380
|
+
if (!posStart) {
|
|
381
|
+
posStart = options.position;
|
|
382
|
+
}
|
|
383
|
+
return "[removed]";
|
|
384
|
+
}
|
|
385
|
+
} else {
|
|
386
|
+
return next(tag, html, options);
|
|
387
|
+
}
|
|
388
|
+
},
|
|
389
|
+
remove: function (html) {
|
|
390
|
+
var rethtml = "";
|
|
391
|
+
var lastPos = 0;
|
|
392
|
+
_.forEach(removeList, function (pos) {
|
|
393
|
+
rethtml += html.slice(lastPos, pos[0]);
|
|
394
|
+
lastPos = pos[1];
|
|
395
|
+
});
|
|
396
|
+
rethtml += html.slice(lastPos);
|
|
397
|
+
return rethtml;
|
|
398
|
+
},
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* remove html comments
|
|
404
|
+
*
|
|
405
|
+
* @param {String} html
|
|
406
|
+
* @return {String}
|
|
407
|
+
*/
|
|
408
|
+
function stripCommentTag(html) {
|
|
409
|
+
var retHtml = "";
|
|
410
|
+
var lastPos = 0;
|
|
411
|
+
while (lastPos < html.length) {
|
|
412
|
+
var i = html.indexOf("<!--", lastPos);
|
|
413
|
+
if (i === -1) {
|
|
414
|
+
retHtml += html.slice(lastPos);
|
|
415
|
+
break;
|
|
416
|
+
}
|
|
417
|
+
retHtml += html.slice(lastPos, i);
|
|
418
|
+
var j = html.indexOf("-->", i);
|
|
419
|
+
if (j === -1) {
|
|
420
|
+
break;
|
|
421
|
+
}
|
|
422
|
+
lastPos = j + 3;
|
|
423
|
+
}
|
|
424
|
+
return retHtml;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* remove invisible characters
|
|
429
|
+
*
|
|
430
|
+
* @param {String} html
|
|
431
|
+
* @return {String}
|
|
432
|
+
*/
|
|
433
|
+
function stripBlankChar(html) {
|
|
434
|
+
var chars = html.split("");
|
|
435
|
+
chars = chars.filter(function (char) {
|
|
436
|
+
var c = char.charCodeAt(0);
|
|
437
|
+
if (c === 127) return false;
|
|
438
|
+
if (c <= 31) {
|
|
439
|
+
if (c === 10 || c === 13) return true;
|
|
440
|
+
return false;
|
|
441
|
+
}
|
|
442
|
+
return true;
|
|
443
|
+
});
|
|
444
|
+
return chars.join("");
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
exports.whiteList = getDefaultWhiteList();
|
|
448
|
+
exports.getDefaultWhiteList = getDefaultWhiteList;
|
|
449
|
+
exports.onTag = onTag;
|
|
450
|
+
exports.onIgnoreTag = onIgnoreTag;
|
|
451
|
+
exports.onTagAttr = onTagAttr;
|
|
452
|
+
exports.onIgnoreTagAttr = onIgnoreTagAttr;
|
|
453
|
+
exports.safeAttrValue = safeAttrValue;
|
|
454
|
+
exports.escapeHtml = escapeHtml;
|
|
455
|
+
exports.escapeQuote = escapeQuote;
|
|
456
|
+
exports.unescapeQuote = unescapeQuote;
|
|
457
|
+
exports.escapeHtmlEntities = escapeHtmlEntities;
|
|
458
|
+
exports.escapeDangerHtml5Entities = escapeDangerHtml5Entities;
|
|
459
|
+
exports.clearNonPrintableCharacter = clearNonPrintableCharacter;
|
|
460
|
+
exports.friendlyAttrValue = friendlyAttrValue;
|
|
461
|
+
exports.escapeAttrValue = escapeAttrValue;
|
|
462
|
+
exports.onIgnoreTagStripAll = onIgnoreTagStripAll;
|
|
463
|
+
exports.StripTagBody = StripTagBody;
|
|
464
|
+
exports.stripCommentTag = stripCommentTag;
|
|
465
|
+
exports.stripBlankChar = stripBlankChar;
|
|
466
|
+
exports.attributeWrapSign = '"';
|
|
467
|
+
exports.cssFilter = defaultCSSFilter;
|
|
468
|
+
exports.getDefaultCSSWhiteList = getDefaultCSSWhiteList;
|