@blueking/xss-filter
| Install | |
|---|---|
npm install @blueking/xss-filter |
|
| Latest Version: | 0.0.11 |
| License: | MIT |
| Last Updated: | Oct 12, 2026 |
| Links: | npm |
蓝鲸 XSS 过滤工具
一个基于 xss 库封装轻量级的工具,用于过滤字符串或 JSON 中 HTML 内容片段的 XSS(跨站脚本)攻击。支持 Vue(Vue 2 和 Vue 3)指令,或者独立使用过滤方法。
安装
npm install @blueking/xss-filter
使用
Vue 指令
注册指令
// Vue 3
import { createApp } from 'vue';
import { BkXssFilterDirective } from '@blueking/xss-filter';
import App from './app.vue';
createApp(App).use(BkXssFilterDirective).mount('#app');
// Vue 2
import Vue from 'vue';
import { BkXssFilterDirective } from '@blueking/xss-filter';
Vue.use(BkXssFilterDirective);
new Vue({
render: h => h(App),
}).$mount('#app');
在模板中使用
<!-- 默认 -->
<div v-bk-xss-html="userContent"></div>
<!-- 纯文本模式,只保留html内容中标签内的纯文本 -->
<div v-bk-xss-html.plain="userContent"></div>
<!-- 传入对象模式(自定义选项) -->
<div v-bk-xss-html="{ content: userContent, options: { whiteList: { p: [] } } }"></div>
<!-- 黑名单:去掉 a 标签及其内容(对纯文本模式同样生效) -->
<div v-bk-xss-html="{ content: userContent, options: { blackList: ['a'] } }"></div>
whiteList会与内置白名单深合并,只能新增标签或属性,无法移除内置标签。如需禁用内置白名单中的标签(如a),请使用blackList。指令中单次传入的
options与全局defaultOptions为浅合并,单次传入的blackList会整体覆盖全局配置中的blackList。
配置全局选项
以 vue 3 项目为例:
import { createApp } from 'vue';
import App from './App.vue';
import { BkXssFilterDirective } from '@blueking/xss-filter';
import type { XssDirectiveConfig } from '@blueking/xss-filter';
const app = createApp(App);
// 安装指令并配置全局选项
app.use(BkXssFilterDirective, {
defaultOptions: {
// 全局 XSS 配置选项
whiteList: {
a: ['href', 'title', 'target', 'rel']
}
},
plainModeByDefault: false // 默认使用富文本模式
} as XssDirectiveConfig);
app.mount('#app');
独立使用过滤方法
从模块中导入函数:
import { filterXss, deepFilterXss, filterPlainText } from '@blueking/xss-filter';
// 过滤掉所有非白名单内的 HTML 标签和属性
const safeString = filterXss('<script>alert("XSS")</script>');
// 过滤掉所有 HTML 标签和属性,只保留标签内的纯文本
const safeText = filterPlainText('<script>alert("XSS")</script>');
// 通过黑名单去掉 a 标签及其内容,其余白名单标签照常保留
const noLink = filterXss('<p>前<a href="https://x.com">链接</a>后</p>', { blackList: ['a'] }); // <p>前后</p>
// 过滤掉 JSON 中 HTML 片段,默认采用 filterPlainText 方法只保留 HTML 标签内的纯文本,可配置为filterXss并传入自定义过滤选项
const safeObject = deepFilterXss({ html: '<script>alert("XSS")</script>' });
API 参考
函数
-
filterXss(html: string, options?: XssOptions): string过滤掉所有非白名单内的 HTML 标签和属性。 -
filterPlainText(text: string, options?: XssOptions): string过滤掉所有 HTML 标签和属性,只保留标签内的纯文本。options中仅blackList生效,命中的标签内容也会被去掉。 -
deepFilterXss(obj: T, filterFn?: FilterFunction = filterPlainText, options?: XssOptions): T过滤掉 JSON 中 HTML 片段,默认采用filterPlainText方法只保留 HTML 标签内的纯文本,可配置为filterXss并传入自定义过滤选项。
interface XssOptions {
// 白名单,不在白名单上的标签将被过滤,不在白名单上的属性也会被过滤
whiteList?: Record<string, string[]>;
// 黑名单,优先级高于白名单,命中的标签会连同标签内的内容一起被去掉
blackList?: string[];
// 去掉不在白名单上的标签,但保留标签里的纯文本内容
stripIgnoreTag?: boolean;
// 去掉不在白名单上的标签及里面的纯文本内容
stripIgnoreTagBody?: boolean | string[];
// 去掉 HTML 备注
allowCommentTag?: boolean;
// 自定义匹配到标签时的处理方法
// tag是当前的标签名称,html是该标签的的html。如果返回字符串,则当前标签将被替换为该字符串;如果不返回任何值,则使用默认处理方法(在白名单上:通过onTagAttr来过滤属性;不在白名单上:通过onIgnoreTag指定)
onTag?: (tag: string, html: string, options: Record<string, boolean | number>) => string | undefined;
// 自定义匹配到标签的属性时的处理方法
// tag是当前的标签名称,name是当前属性名称,value是属性值,isWhiteAttr表示是否为白名单上属性
// 如果返回字符串,则当前属性值会被替换为该字符串;如果不返回任何值,则使用默认处理方法(在白名单上:调用safeAttrValue来过滤属性值,并输出该属性;不在白名单上:通过onIgnoreTagAttr指定)
onTagAttr?: (tag: string, name: string, value: string, isWhiteAttr: boolean) => string | undefined;
// 自定义匹配到不在白名单上的标签时的处理方法
// 参数与onTag相同。如果返回字符串,则当前标签将被替换为该字符串;如果不返回任何值,则使用默认处理方法(通过escape指定)
onIgnoreTag?: (tag: string, html: string, options: Record<string, boolean | number>) => string | undefined;
// 自定义匹配到不在白名单上的标签时的处理方法
// 参数与onTagAttr相同。如果返回字符串,则当前属性值会被替换为该字符串;如果不返回任何值,则使用默认处理方法(删除该属性)
onIgnoreTagAttr?: (tag: string, name: string, value: string, isWhiteAttr: boolean) => string | undefined;
// 自定义 HTML 转义函数
// 默认返回 html.replace(/</g, "<").replace(/>/g, ">");,不建议修改
escapeHtml?: (html: string) => string;
// 自定义标签属性值的转义函数
// 参数与onTagAttr相同。返回一个值表示该属性值
safeAttrValue?: (tag: string, name: string, value: string) => string | undefined;
css?: boolean | CssFilterOptions;
imgSrcMode?: 'base64' | string[] | 'none'; // 支持三种模式:base64、信任域名、不限制
}
// style属性值过滤接口
interface CssFilterOptions {
// css属性白名单
whiteList?: {
[key: string]: boolean | ((value: string) => boolean) | RegExp;
};
// 自定义匹配到在白名单上的属性时的处理方法
// 返回字符串表示覆盖此段CSS,不返回任何值表示使用默认生成方法,即name:value
onAttr?: (name: string, value: string, options) => string | undefined;
// 自定义匹配到不在白名单上的属性时的处理方法
// 返回字符串表示覆盖此段CSS,不返回任何值表示使用默认生成方法,即去掉此段CSS
onIgnoreAttr?: (name: string, value: string, options) => string | undefined;
}
内置默认的白名单配置
// 标签属性白名单
{
"a": ["href", "title", "target", "rel", "id", "class", "style"],
"aside": ["id", "class", "style"],
"audio": ["src", "autoplay", "controls", "loop", "muted"],
"b": [],
"blockquote": ["id", "class", "style"],
"body": ["id", "class", "style"],
"br": [],
"button": ["type", "id", "class", "style"],
"canvas": ["width", "height"],
"code": ["id", "class"],
"div": ["id", "class", "style"],
"em": [],
"h1": ["id", "class", "style"],
"h2": ["id", "class", "style"],
"h3": ["id", "class", "style"],
"h4": ["id", "class", "style"],
"h5": ["id", "class", "style"],
"h6": ["id", "class", "style"],
"hr": [],
"i": [],
"img": ["src", "alt", "title", "width", "height", "id", "class", "style"],
"li": ["id", "class", "style"],
"nav": ["id", "class", "style"],
"ol": ["id", "class", "style"],
"p": ["id", "class", "style"],
"pre": ["class"],
"s": [],
"section": ["id", "class", "style"],
"span": ["id", "class", "style"],
"strong": [],
"style": [],
"table": ["id", "class", "style", "border", "cellspacing", "cellpadding"],
"textarea": ["id", "class", "style"],
"tbody": ["id", "class", "style"],
"td": ["id", "class", "style", "colspan", "rowspan"],
"th": ["id", "class", "style", "colspan", "rowspan"],
"thead": ["id", "class", "style"],
"tr": ["id", "class", "style"],
"u": [],
"ul": ["id", "class", "style"],
"video": ["src", "autoplay", "controls", "loop", "muted"]
}
// style属性值白名单
{
'background': true,
'background-attachment': true,
'background-clip': true,
'background-color': true,
'background-image': true,
'background-origin': true,
'background-position': true,
'background-repeat': true,
'background-size': true,
'border': true,
'border-bottom': true,
'border-bottom-color': true,
'border-bottom-left-radius': true,
'border-bottom-right-radius': true,
'border-bottom-style': true,
'border-bottom-width': true,
'border-collapse': true,
'border-color': true,
'border-image': true,
'border-image-outset': true,
'border-image-repeat': true,
'border-image-slice': true,
'border-image-source': true,
'border-image-width': true,
'border-left': true,
'border-left-color': true,
'border-left-style': true,
'border-left-width': true,
'border-radius': true,
'border-right': true,
'border-right-color': true,
'border-right-style': true,
'border-right-width': true,
'border-spacing': true,
'border-style': true,
'border-top': true,
'border-top-color': true,
'border-top-left-radius': true,
'border-top-right-radius': true,
'border-top-style': true,
'border-top-width': true,
'border-width': true,
'box-decoration-break': true,
'box-shadow': true,
'box-sizing': true,
'box-snap': true,
'box-suppress': true,
'break-after': true,
'break-before': true,
'break-inside': true,
'clear': true,
'color': true,
'color-interpolation-filters': true,
'display': true,
'display-inside': true,
'display-list': true,
'display-outside': true,
'font': true,
'font-family': true,
'font-feature-settings': true,
'font-kerning': true,
'font-language-override': true,
'font-size': true,
'font-size-adjust': true,
'font-stretch': true,
'font-style': true,
'font-synthesis': true,
'font-variant': true,
'font-variant-alternates': true,
'font-variant-caps': true,
'font-variant-east-asian': true,
'font-variant-ligatures': true,
'font-variant-numeric': true,
'font-variant-position': true,
'font-weight': true,
'height': true,
'letter-spacing': true,
'lighting-color': true,
'list-style': true,
'list-style-image': true,
'list-style-position': true,
'list-style-type': true,
'margin': true,
'margin-bottom': true,
'margin-left': true,
'margin-right': true,
'margin-top': true,
'max-height': true,
'max-width': true,
'min-height': true,
'min-width': true,
'padding': true,
'padding-bottom': true,
'padding-left': true,
'padding-right': true,
'padding-top': true,
'text-align': true,
'text-align-last': true,
'text-combine-upright': true,
'text-decoration': true,
'text-decoration-color': true,
'text-decoration-line': true,
'text-decoration-skip': true,
'text-decoration-style': true,
'text-emphasis': true,
'text-emphasis-color': true,
'text-emphasis-position': true,
'text-emphasis-style': true,
'text-height': true,
'text-indent': true,
'text-justify': true,
'text-orientation': true,
'text-overflow': true,
'text-shadow': true,
'text-space-collapse': true,
'text-transform': true,
'text-underline-position': true,
'text-wrap': true,
'width': true,
'word-break': true,
'word-spacing': true,
'word-wrap': true,
}
Related Packages
A Nuxt module to sanitise HTML to protect against XSS attacks
A Nuxt 3 module that integrates DOMPurify for sanitizing HTML content and protec...
A Nuxt module that integrates sanitize-html for sanitizing HTML content and prot...
Version History
| Version | Released | License |
|---|---|---|
| 0.0.11 | MIT | |
| 0.0.10 | MIT | |
| 0.0.9 | MIT | |
| 0.0.8 | MIT | |
| 0.0.7 | MIT | |
| 0.0.6 | MIT | |
| 0.0.5 | MIT | |
| 0.0.4 | MIT | |
| 0.0.3 | MIT | |
| 0.0.2 | MIT | |
| 0.0.1 | MIT |