Comparing version 0.0.1 to 0.0.2
51
index.js
@@ -36,4 +36,7 @@ /** | ||
li: ['style', 'class'], | ||
em: ['style'], //added by jim | ||
cite: ['style'] //added by jim | ||
ol: ['style', 'class'], | ||
em: ['style'], | ||
cite: ['style'], | ||
section:['style', 'class'], | ||
blockquote: ['style', 'class'], | ||
}; | ||
@@ -72,5 +75,9 @@ | ||
* @param {string} html 标签HTML代码(包括属性值) | ||
* @param {object} options 更多属性: | ||
* position:在返回的HTML代码中的开始位置 | ||
* originalPosition:在原HTML代码中的开始位置 | ||
* isClosing:是否为闭合标签,如</a> | ||
* @return {string} 若不返回任何值,则默认替换<>为<> | ||
*/ | ||
var defaultOnIgnoreTag = function (tag, html) { | ||
var defaultOnIgnoreTag = function (tag, html, options) { | ||
return noTag(html); | ||
@@ -109,2 +116,3 @@ }; | ||
var quoteStart = false; | ||
var currentPos = 0; | ||
@@ -120,4 +128,10 @@ /** | ||
var tmpName = false; | ||
function addAttr (name, value) { | ||
name = name.replace(/[^a-zA-Z0-9_:\.\-]/img, '').toLowerCase().trim(); | ||
var hasSprit = false; | ||
var addAttr = function (name, value) { | ||
name = name.trim(); | ||
if (!hasSprit && name === '/') { | ||
hasSprit = true; | ||
return; | ||
}; | ||
name = name.replace(/[^a-zA-Z0-9_:\.\-]/img, '').toLowerCase(); | ||
if (name.length < 1) return; | ||
@@ -144,3 +158,3 @@ if (whites.indexOf(name) !== -1) { | ||
} | ||
} | ||
}; | ||
for (var i = 0, len = attrs.length; i < len; i++) { | ||
@@ -187,2 +201,3 @@ var c = attrs[i]; | ||
} | ||
if (hasSprit) _attrs.push('/'); | ||
return _attrs.join(' '); | ||
@@ -216,3 +231,8 @@ }; | ||
// 过滤不合法的标签 | ||
var tagHtml = onIgnoreTag(tagName, tag); | ||
var options = { | ||
isClosing: (spos === 2), | ||
position: rethtml.length, | ||
originalPosition: currentPos - tag.length + 1 | ||
}; | ||
var tagHtml = onIgnoreTag(tagName, tag, options); | ||
if (typeof(tagHtml) === 'undefined') { | ||
@@ -226,7 +246,7 @@ tagHtml = noTag(tag); | ||
// 逐个分析字符 | ||
for (var i = 0, len = html.length; i < len; i++) { | ||
var c = html[i]; | ||
for (var currentPos = 0, len = html.length; currentPos < len; currentPos++) { | ||
var c = html[currentPos]; | ||
if (tagStart === false) { | ||
if (c === '<') { | ||
tagStart = i; | ||
tagStart = currentPos; | ||
continue; | ||
@@ -237,9 +257,9 @@ } | ||
if (c === '<') { | ||
rethtml += noTag(html.slice(lastPos, i)); | ||
tagStart = i; | ||
lastPos = i; | ||
rethtml += noTag(html.slice(lastPos, currentPos)); | ||
tagStart = currentPos; | ||
lastPos = currentPos; | ||
continue; | ||
} | ||
if (c === '>') { | ||
addNewTag(html.slice(tagStart, i + 1), i); | ||
addNewTag(html.slice(tagStart, currentPos + 1), currentPos); | ||
tagStart = false; | ||
@@ -270,1 +290,4 @@ continue; | ||
exports.onIgnoreTag = defaultOnIgnoreTag; | ||
// 工具函数 | ||
exports.utils = require('./utils'); |
{ | ||
"name": "xss", | ||
"main": "./index.js", | ||
"version": "0.0.1", | ||
"version": "0.0.2", | ||
"description": "Remove XSS attack vectors from user-supplied HTML", | ||
@@ -6,0 +6,0 @@ "author": "leizongmin <leizongmin@gmail.com> (http://ucdok.com)", |
@@ -0,1 +1,3 @@ | ||
[![Build Status](https://secure.travis-ci.org/leizongmin/js-xss.png?branch=master)](http://travis-ci.org/leizongmin/js-xss) | ||
过滤XSS攻击 | ||
@@ -34,9 +36,28 @@ ====== | ||
xss.whiteList['p'] = ['class', 'style']; | ||
// 删除默认的白名单标签 | ||
delete xss.whiteList['div']; | ||
// 自定义处理属性值函数 | ||
xss.onTagAttr = function (tag, attr, vaule) { | ||
// tag:当前标签名(小写) | ||
// attr:当前属性名(小写) | ||
// value:当前属性值 | ||
// 返回新的属性值,如果想使用默认的处理方式,不返回任何值即可 | ||
// tag:当前标签名(小写) | ||
// attr:当前属性名(小写) | ||
// value:当前属性值 | ||
// 返回新的属性值,如果想使用默认的处理方式,不返回任何值即可 | ||
// 比如把属性值中的双引号替换为&quote;:return value.replace(/"/g, '&quote;'); | ||
// 以下为默认的处理代码: | ||
if (attr === 'href' || attr === 'src') { | ||
if (/\/\*|\*\//mg.test(value)) { | ||
return '#'; | ||
} | ||
if (/^[\s"'`]*((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):/ig.test(value)) { | ||
return '#'; | ||
} | ||
} else if (attr === 'style') { | ||
if (/\/\*|\*\//mg.test(value)) { | ||
return '#'; | ||
} | ||
if (/((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):/ig.test(value)) { | ||
return ''; | ||
} | ||
} | ||
}; | ||
@@ -46,5 +67,8 @@ | ||
xss.onIgnoreTag = function (tag, html) { | ||
// tag:当前标签名(小写),如:a | ||
// html:当前标签的HTML代码,如:<a href="ooxx"> | ||
// 返回新的标签HTML代码,如果想使用默认的处理方式,不返回任何值即可 | ||
// tag:当前标签名(小写),如:a | ||
// html:当前标签的HTML代码,如:<a href="ooxx"> | ||
// 返回新的标签HTML代码,如果想使用默认的处理方式,不返回任何值即可 | ||
// 比如将标签替换为[removed]:return '[removed]'; | ||
// 以下为默认的处理代码: | ||
return html.replace(/</g, '<').replace(/>/g, '>'); | ||
} | ||
@@ -57,5 +81,5 @@ ``` | ||
var options = { | ||
whiteList: {}, // 若不指定,则使用默认配置 | ||
onTagAttr: function () {}, // 若不指定,则使用默认配置 | ||
onIgnoreTag: function () {} // 若不指定,则使用默认配置 | ||
whiteList: {}, // 若不指定则使用默认配置,可参考xss.whiteList | ||
onTagAttr: function () {}, // 若不指定则使用默认配置,可参考xss.onTagAttr | ||
onIgnoreTag: function () {} // 若不指定则使用默认配置,可参考xss.onIgnoreTag | ||
}; | ||
@@ -66,3 +90,5 @@ var html = xss('<script>alert("xss");</script>', options); | ||
## 其他应用 | ||
## 测试 | ||
@@ -69,0 +95,0 @@ |
@@ -52,2 +52,7 @@ /** | ||
// 单个闭合标签 | ||
assert.equal(xss('<img src="#"/>'), '<img src="#" />'); | ||
assert.equal(xss('<img src="#" />'), '<img src="#" />'); | ||
assert.equal(xss('<img src="#"//>'), '<img src="#">'); | ||
}); | ||
@@ -84,2 +89,3 @@ | ||
// 过滤标签 | ||
assert.equal(xss('<ooxx xxyy>ookk</ooxx><img>', { | ||
@@ -90,3 +96,2 @@ onIgnoreTag: function (tag, html) { | ||
}), 'ookk<img>'); | ||
assert.equal(xss('<ooxx xxyy>ookk</ooxx><img>', { | ||
@@ -98,2 +103,31 @@ onIgnoreTag: function (tag, html) { | ||
// 检验附加属性 | ||
var isClosing = []; | ||
var position = []; | ||
var originalPosition = []; | ||
var html = xss('TTG:<ooxx href="ooy" >ds</ooxx>--ds d<yy hh uu>', { | ||
onIgnoreTag: function (tag, html, options) { | ||
isClosing.push(options.isClosing); | ||
position.push(options.position); | ||
originalPosition.push(options.originalPosition); | ||
} | ||
}); | ||
//console.log(html); | ||
assert.deepEqual(isClosing, [false, true, false]); | ||
assert.deepEqual(position, [4, 30, 50]); | ||
assert.deepEqual(originalPosition, [4, 24, 38]); | ||
// 替换检验 utils.tagFilter() | ||
var filter = xss.utils.tagFilter(['script']); | ||
var html = xss('<b >script is <script t="d">alert("xss"); ooxx()</script>, wahaha!!</b>', { | ||
onIgnoreTag: filter.onIgnoreTag | ||
}); | ||
assert.equal(filter.filter(html), '<b>script is , wahaha!!</b>'); | ||
var filter = xss.utils.tagFilter(['x2']); | ||
var html = xss('<x1></b><x2>dds</x2><x3>fd</x3>', { | ||
onIgnoreTag: filter.onIgnoreTag | ||
}); | ||
assert.equal(filter.filter(html), '<x1></b><x3>fd</x3>'); | ||
}); | ||
@@ -100,0 +134,0 @@ |
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
134547
12
525
136