必须过滤script标签和on事件属性,否则用户输入直接进DOM会引发XSS;前端用DOMPurify.sanitize()默认移除script、iframe及on*属性,后端须二次净化并显式配置协议白名单,富文本渲染需隔离于sandbox iframe且配合CSP nonce策略。

HTML输入内容必须过滤script和on事件属性
不做过滤的用户输入直接进DOM,等于给XSS开绿灯。哪怕只渲染一条评论、一个昵称或搜索关键词,只要没处理,<script>或onclick就能触发执行。
- 前端用
DOMPurify.sanitize()是最轻量且可靠的方案,它默认移除<script>、<iframe>、所有on*属性(如onerror)、javascript:伪协议 - 后端不能只靠前端过滤——必须二次净化,推荐
jsoup(Java)或bleach(Python),它们按白名单控制标签/属性,比正则更防绕过 - 别信“我只允许p、span、a”,如果
<a href="javascript:alert(1)">能过,说明白名单没禁掉危险协议,必须显式配置allowed_protocols=['https', 'http']
富文本渲染必须隔离在sandbox iframe中
允许用户发带格式的内容(比如编辑器输出),就绝不能用innerHTML直接插入主页面。即使做了净化,仍可能被新浏览器特性或0day绕过。
- 把渲染结果放进
<iframe sandbox="allow-scripts allow-same-origin">,但务必去掉allow-top-navigation和allow-popups - iframe src设为
blob:URL或独立子域(如preview.example.com),避免共享主站cookie和localStorage - 父子通信必须用
postMessage,且在接收端验证event.origin和event.source,否则沙箱形同虚设
CSP策略不能只写default-src 'self'
Content-Security-Policy是最后一道防线,但很多团队只配个default-src 'self'就以为万事大吉——这根本挡不住内联脚本或动态eval。
- 禁用
'unsafe-inline'和'unsafe-eval',改用nonce:服务端生成随机值,写入<script nonce="abc123">,并在CSP头中声明script-src 'nonce-abc123' - 图片、字体等资源要单独放开,比如
img-src https: data:,避免因CSP拦截导致页面残缺 - 开发期开启
report-uri或report-to,收集违规行为,而不是等被黑了才看到日志
语义结构错误会直接破坏无障碍合规
WCAG 2.1 AA级要求不是“建议”,而是法律风险点。屏幕阅读器依赖<main>、<header>等标签建立导航树,写错等于主动拒斥残障用户。
立即学习“前端免费学习笔记(深入)”;
-
<main>必须且只能出现一次,且不能被<div>或<section>包裹——否则隐式role="main"丢失,键盘用户无法Ctrl+Alt+O跳转 - 标题层级断裂(如
<h1>后直接<h4>)比没写标签更糟,会导致阅读器把整页当平铺文本读,丧失结构感知 -
<table>必须有<caption>,<th>必须带scope或headers绑定,否则数据行列关系对辅助技术完全不可见
scope的<th>不会报错,但会让视障用户在表格里彻底迷失;一段漏掉nonce的内联脚本可能几个月都运行正常,直到某次浏览器更新启用新解析规则才暴露。防御性实践不是堆砌工具,而是把每个HTML标签当作契约来履行。



















