电商详情页html安全必须采用属性白名单+协议校验双锁死,仅转义或csp无效;需严格限制href/src协议、禁用危险属性、避免innerhtml拼接,区分纯文本/结构化/富文本三类渲染路径。

电商详情页里用户可控字段(如商品标题、规格描述、卖家留言)一旦直插 HTML,onerror、javascript:、data: 就会立刻执行——不是“可能被利用”,而是“必然触发”。必须用属性白名单 + 协议校验双锁死,单靠转义或 CSP 都拦不住。
为什么只配 HTML.AllowedAttributes = a[href], img[src] 还是中招
漏配导致的漏洞比想象中更隐蔽:
-
href和src不加协议限制,javascript:alert(1)会原样通过 -
img标签漏掉alt属性,某些净化器会因结构不完整而降级处理,放行后续危险内容 -
iframe被禁用,但若白名单里单独写了sandbox,攻击者可构造<iframe sandbox="allow-scripts"></iframe>绕过隔离 -
class和id看似无害,但若前端 JS 用document.getElementById(userInput)做动态操作,就变成 DOM XSS 入口
href 和 src 必须做协议白名单校验,不能只靠转义
HTML 转义对 javascript: 类注入完全无效,浏览器解析时直接进入执行上下文:
- 服务端校验必须在净化前完成:只允许
https://、http://、/、#开头,拒绝javascript:、data:、vbscript: - 前端动态赋值时,别写
el.setAttribute('href', userInput)——这绕过所有服务端过滤逻辑 - Go 的
html/template只有变量类型为template.URL才自动 URL 编码;普通字符串拼接仍危险 - Node.js 用
sanitize-html时,需显式配置allowedSchemes: ['http', 'https', '/'],否则默认放行全部
富文本渲染不能走 innerHTML + 白名单净化闭环
很多人以为「先用 DOMPurify 清洗,再 el.innerHTML = cleanHtml」就安全了,其实错在信任边界断裂:
-
DOMPurify.sanitize()输出的是字符串,赋给innerHTML后浏览器会重新解析——如果漏配svg/onload,照样执行 - 更常见的是:数据入库时已净化,读取后又被模板引擎拼进
<div>${content}</div>,而模板关闭了转义(如 Nunjucks 的{% raw %}{{ content }}{% endraw %}),等于白净化 - 真正安全路径只有两条:
textContent渲染纯文本;或用document.createElement+setAttribute逐个构造节点,不走字符串插入 - 电商详情页中“规格参数表”这类结构化内容,建议用 JSON Schema 描述字段类型,前端按 schema 动态生成 DOM,彻底规避 HTML 拼接
CSP 不能替代属性白名单,但漏配白名单时 CSP 彻底失效
Content-Security-Policy: script-src 'self' 对内联事件处理器毫无约束力:
- 白名单漏掉一个
onmouseover,CSP 就无法阻止<div onmouseover="fetch('/api/steal')"> <li>白名单严格但没配 CSP?攻击者可用 <code><base href="https://evil.com">劫持所有相对 URL 请求 - 二者必须共存:白名单负责 DOM 结构干净,CSP 负责执行环境受限;缺一不可
- 电商页面尤其要配
base-uri 'self'和form-action 'self',防跳转和表单提交被劫持
电商详情页的 HTML 安全不是“加一层过滤就完事”,而是从字段设计开始就要区分「纯文本」「结构化数据」「富文本」三类,每类走不同渲染路径。最容易被忽略的是:卖家后台编辑的商品描述,前端展示时是否复用了同一套净化逻辑——往往后台宽松、前台紧,中间链路一断,整个防线就垮了。











