leizongmin/js-xss
GitHub: leizongmin/js-xss
基于白名单机制的 HTML 消毒库,用于过滤不受信任的 HTML 以防止 XSS 攻击。
Stars: 5316 | Forks: 632
[][npm-url]
[](https://github.com/leizongmin/js-xss/actions/workflows/nodejs.yml)
[][coveralls-url]
[][david-url]
[][node-url]
[][download-url]
[][download-url]
# 通过白名单配置过滤不受信任的 HTML(以防止 XSS)。
[](https://greenkeeper.io/)

`xss` 是一个用于过滤用户输入以防止 XSS 攻击的模块。
([什么是 XSS 攻击?](http://en.wikipedia.org/wiki/Cross-site_scripting))
**项目主页:** http://jsxss.com
**在线体验:** http://jsxss.com/en/try.html
**[中文版文档](https://github.com/leizongmin/js-xss/blob/master/README.zh.md)**
## 功能特性
- 通过白名单指定允许的 HTML 标签及其属性
- 使用自定义函数处理任何标签或属性。
## 参考资料
- [XSS 过滤器绕过备忘单](https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet)
- [Data URI scheme](http://en.wikipedia.org/wiki/Data_URI_scheme)
- [使用 Data URI Scheme 的 XSS](http://hi.baidu.com/badzzzz/item/bdbafe83144619c199255f7b)
## 基准测试(仅供参考)
- xss 模块:22.53 MB/s
- `validator@0.3.7` 模块中的 `xss()` 函数:6.9 MB/s
测试代码请参考 `benchmark` 目录。
## 使用 xss 模块的项目
- **nodeclub** - 一个使用 MongoDB 的 Node.js 论坛 - https://github.com/cnodejs/nodeclub
- **cnpmjs.org** - 企业私有 npm registry 和 Web 服务 - https://github.com/cnpm/cnpmjs.org
- **cocalc.com** - 协作计算与数据科学 - https://cocalc.com
## 安装
### NPM
```
npm install xss
```
### Bower
```
bower install xss
```
或者
```
bower install https://github.com/leizongmin/js-xss.git
```
## 用法
### 在 Node.js 上
```
var xss = require("xss");
var html = xss('');
console.log(html);
```
### 获取过滤后的 HTML 和被移除的元素
你可以使用 `filterXSSWithResult` 来同时获取过滤后的 HTML 以及被移除的标签/属性列表:
```
var xss = require("xss");
var result = xss.filterXSSWithResult('click');
console.log(result.html);
// Output: "<script>alert(\"xss\");</script>click"
console.log(result.removed);
// Output: [
// { type: "tag", tag: "script", html: "", isClosing: true },
// { type: "attr", tag: "a", attr: "onclick", value: "evil()" }
// ]
```
### 在浏览器上
Shim 模式(参考文件 `test/test.html`):
```
```
AMD 模式 - shim:
```
```
**注意:请不要在生产环境中使用 URL https://rawgit.com/leizongmin/js-xss/master/dist/xss.js。**
## 命令行工具
### 处理文件
你可以使用 xss 命令行工具来处理文件。用法:
```
xss -i -o
```
示例:
```
xss -i origin.html -o target.html
```
### 交互式测试
运行以下命令,然后你就可以在命令行中输入 HTML 代码,并查看过滤后的输出:
```
xss -t
```
欲了解更多详情,请运行 `$ xss -h` 查看。
## 自定义过滤规则
在使用 `xss()` 函数时,可以通过第二个参数指定自定义规则:
```
options = {}; // Custom rules
html = xss('', options);
```
为了避免每次都传递 `options`,你还可以通过创建一个 `FilterXSS` 实例,以更快的方式来实现:
```
options = {}; // Custom rules
myxss = new xss.FilterXSS(options);
// then apply myxss.process()
html = myxss.process('');
```
`options` 中各参数的详细信息将在下文描述。
### 白名单
通过指定一个 `whiteList`,例如 `{ 'tagName': [ 'attr-1', 'attr-2' ] }`。不在白名单中的标签和属性将被过滤掉。例如:
```
// only tag a and its attributes href, title, target are allowed
var options = {
whiteList: {
a: ["href", "title", "target"],
},
};
// With the configuration specified above, the following HTML:
// Hello
// would become:
// <i>Hello</i>
```
关于默认的白名单,请参考 `xss.whiteList`。
也支持使用 `allowList`,其功能与 `whiteList` 相同。
### 自定义匹配到的标签的处理函数
通过 `onTag` 指定处理函数:
```
function onTag(tag, html, options) {
// tag is the name of current tag, e.g. 'a' for tag
// html is the HTML of this tag, e.g. '' for tag
// options is some addition informations:
// isWhite boolean, whether the tag is in whitelist
// isClosing boolean, whether the tag is a closing tag, e.g. true for
// position integer, the position of the tag in output result
// sourcePosition integer, the position of the tag in input HTML source
// If a string is returned, the current tag would be replaced with the string
// If return nothing, the default measure would be taken:
// If in whitelist: filter attributes using onTagAttr, as described below
// If not in whitelist: handle by onIgnoreTag, as described below
}
```
### 自定义匹配到的标签属性的处理函数
通过 `onTagAttr` 指定处理函数:
```
function onTagAttr(tag, name, value, isWhiteAttr) {
// tag is the name of current tag, e.g. 'a' for tag
// name is the name of current attribute, e.g. 'href' for href="#"
// isWhiteAttr whether the attribute is in whitelist
// If a string is returned, the attribute would be replaced with the string
// If return nothing, the default measure would be taken:
// If in whitelist: filter the value using safeAttrValue as described below
// If not in whitelist: handle by onIgnoreTagAttr, as described below
}
```
### 自定义不在白名单中的标签的处理函数
通过 `onIgnoreTag` 指定处理函数:
```
function onIgnoreTag(tag, html, options) {
// Parameters are the same with onTag
// If a string is returned, the tag would be replaced with the string
// If return nothing, the default measure would be taken (specifies using
// escape, as described below)
}
```
### 自定义不在白名单中的属性的处理函数
通过 `onIgnoreTagAttr` 指定处理函数:
```
function onIgnoreTagAttr(tag, name, value, isWhiteAttr) {
// Parameters are the same with onTagAttr
// If a string is returned, the value would be replaced with this string
// If return nothing, then keep default (remove the attribute)
}
```
### 自定义 HTML 转义函数
通过 `escapeHtml` 指定处理函数。以下是默认的函数 **(不建议修改)**:
```
function escapeHtml(html) {
return html.replace(//g, ">");
}
```
### 自定义属性值的转义函数
通过 `safeAttrValue` 指定处理函数:
```
function safeAttrValue(tag, name, value) {
// Parameters are the same with onTagAttr (without options)
// Return the value as a string
}
```
### 自定义 HTML 属性值输出语法
通过指定 `singleQuotedAttributeValue`。使用 `true` 将使用单引号 `'`。否则默认将使用双引号 `"`
```
var options = {
singleQuotedAttributeValue: true,
};
// With the configuration specified above, the following HTML:
// Hello
// would become:
// Hello
```
### 自定义 CSS 过滤器
如果你允许使用 `style` 属性,其值将由 [cssfilter](https://github.com/leizongmin/js-css-filter) 模块处理。cssfilter 模块包含一个默认的 CSS 白名单。你可以像这样为 cssfilter 模块指定选项:
```
myxss = new xss.FilterXSS({
css: {
whiteList: {
position: /^fixed|relative$/,
top: true,
left: true,
},
},
});
html = myxss.process('');
```
如果你不想过滤 `style` 内容,只需将 `css` 选项设置为 `false`:
```
myxss = new xss.FilterXSS({
css: false,
});
```
如需更多帮助,请参阅 https://github.com/leizongmin/js-css-filter
### 快速入门
#### 过滤掉不在白名单中的标签
通过使用 `stripIgnoreTag` 参数:
- `true`:过滤掉不在白名单中的标签
- `false`:默认值:使用配置的 `escape` 函数转义该标签
示例:
如果设置了 `stripIgnoreTag = true`,以下代码:
```
code:
```
将输出过滤后的结果:
```
code:alert(/xss/);
```
#### 过滤掉不在白名单中的标签及其内容
通过使用 `stripIgnoreTagBody` 参数:
- `false|null|undefined`:默认值:不做任何处理
- `'*'|true`:过滤掉所有不在白名单中的标签
- `['tag1', 'tag2']`:仅过滤掉指定的、不在白名单中的标签
示例:
如果设置了 `stripIgnoreTagBody = ['script']`,以下代码:
```
code:
```
将输出过滤后的结果:
```
code:
```
#### 过滤掉 HTML 注释
通过使用 `allowCommentTag` 参数:
- `true`:不做任何处理
- `false`:默认值:过滤掉 HTML 注释
示例:
如果设置了 `allowCommentTag = false`,以下代码:
```
code:
END
```
将输出过滤后的结果:
```
code: END
```
## 示例
### 允许白名单标签中以 `data-` 开头的属性
```
var source = 'he wwww ";
var html = xss(source, {
onIgnoreTag: function (tag, html, options) {
if (tag.substr(0, 2) === "x-") {
// do not filter its attributes
return html;
}
},
});
console.log("%s\nconvert to:\n%s", source, html);
```
结果:
```
he wwww
convert to: <x>he wwww
```
### 解析 HTML 中的图片
```
var source =
'
a
b
c
d';
var list = [];
var html = xss(source, {
onTagAttr: function (tag, name, value, isWhiteAttr) {
if (tag === "img" && name === "src") {
// Use the built-in friendlyAttrValue function to escape attribute
// values. It supports converting entity tags such as < to printable
// characters such as <
list.push(xss.friendlyAttrValue(value));
}
// Return nothing, means keep the default handling measure
},
});
console.log("image list:\n%s", list.join(", "));
```
结果:
```
image list: img1, img2, img3, img4
```
### 过滤掉 HTML 标签(仅保留纯文本)
```
var source = "helloend";
var html = xss(source, {
whiteList: {}, // empty, means filter out all tags
stripIgnoreTag: true, // filter out all HTML not in the whitelist
stripIgnoreTagBody: ["script"], // the script tag is a special case, we need
// to filter out its content
});
console.log("text: %s", html);
```
结果:
```
text: helloend
```
## 许可证
```
Copyright (c) 2012-2018 Zongmin Lei(雷宗民)
http://ucdok.com
The MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
```
hello
';
var html = xss(source, {
onIgnoreTagAttr: function (tag, name, value, isWhiteAttr) {
if (name.substr(0, 5) === "data-") {
// escape its value using built-in escapeAttrValue function
return name + '="' + xss.escapeAttrValue(value) + '"';
}
},
});
console.log("%s\nconvert to:\n%s", source, html);
```
结果:
```
hello
convert to:
hello
```
### 允许以 `x-` 开头的标签
```
var source = "标签:Cilium, CISA项目, CMS安全, GNU通用公共许可证, HTML标签过滤, HTML清理, JavaScript, MITM代理, Naabu, Node.js, NPM, Web安全, XSS过滤, 内容安全, 前端安全, 后端安全, 后端开发, 属性过滤, 数据可视化, 数据清洗, 白名单, 蓝队分析, 输入过滤, 防跨站脚本攻击