非法属性主要指两类高危目标:一是onclick、onsubmit等内联事件处理器,二是javascript:、vbscript:、data:开头的href或src值;data-id等自定义属性合法,contenteditable等标准属性不应误删。

哪些属性算“非法”?先区分事件属性和自定义属性
真正要清理的非法属性,不是所有没在HTML标准里定义的属性,而是两类高危目标:onclick、onsubmit、onerror这类内联事件处理器,以及javascript:、vbscript:、data:开头的href或src值。它们直接执行JS,是XSS主入口。而data-id、data-testid这类自定义属性完全合法,删了反而破坏功能。
常见误判点:
- 把
oninput当成普通属性留着——它和onclick一样危险,必须清 - 看到
contenteditable就删——这是合法全局属性,不该动 - 认为
class或id可有可无——它们常被JS/CSS强依赖,删前必须验证
用 DOMPurify 一次性过滤所有非法属性最省心
手动遍历+removeAttribute能清事件属性,但处理href协议校验、style内联JS、src伪协议等就得写一堆逻辑。DOMPurify 内置完整防护链,调用一行就覆盖全部:
import DOMPurify from 'dompurify';
const clean = DOMPurify.sanitize(dirtyHtml, {
ALLOWED_TAGS: ['p', 'br', 'strong', 'em', 'a'],
ALLOWED_ATTR: ['href', 'class', 'title'],
FORBID_TAGS: ['script', 'iframe'],
FORBID_ATTR: ['onerror', 'onload', 'onfocus'] // 显式禁用,双重保险
});
关键点:
立即学习“前端免费学习笔记(深入)”;
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
-
FORBID_ATTR必须显式列出,否则某些边缘事件属性(如onanimationstart)可能漏掉 -
ALLOWED_ATTR只写你真需要的,别留*——白名单思维才安全 - 如果允许
a标签,href必须配合协议校验规则,否则href="javascript:alert(1)"照进不误
服务端用 Python + bleach 做最终兜底
前端净化只是第一道防线,用户绕过JS就能直发恶意HTML。后端必须用解析器级清洗,推荐bleach(比正则可靠,比lxml轻量):
import bleach
cleaned = bleach.clean(
dirty_html,
tags=['p', 'strong', 'em'],
attributes={'a': ['href']},
protocols=['http', 'https', 'mailto'],
strip=True
)
注意坑:
-
strip=True会删掉所有非法标签及其内容,如果想保留文本(比如<script>hello</script>变成hello),得加strip_comments=False并配filters - 不要用
bleach.linkify()自动转链接——它不校验协议,可能把javascript:alert()也包进去 - 如果业务允许
img,src必须加protocols参数,否则src="data:image/png;base64,..."可能带恶意payload
动态插入的内容最容易漏,必须前置拦截
你用querySelectorAll清完页面,但后续JS用element.innerHTML = '<div onclick="xss()">...</div>',刚才的清理就白做了。真正难的是堵住源头:
- 所有拼接HTML的地方,统一走
DOMPurify.sanitize()再赋值,别信“这个字符串是我自己生成的” - 富文本编辑器输出前强制过一遍净化,哪怕用了Quill或Tiptap,也要在
onSubmit钩子里加 - 后端API返回HTML字段时,字段名加
_sanitized后缀(如content_sanitized),前端只信任带后缀的字段
最后提醒一句:清理属性不是目的,防止执行才是。只要还有eval、setTimeout字符串参数、innerHTML直接赋值,再干净的HTML也会被二次污染。


















