html.escapestring仅转义5个字符,防不了xss;属性值需协议白名单校验;script内禁字符串拼接;template.html是信任开关,须配合bluemonday等库过滤后使用;csp和http头是补丁非替代方案。

html.EscapeString 只能防最基础的 XSS,别把它当万能药
它只转义 、<code>>、"、'、& 这 5 个字符,对 javascript:alert(1)、onerror=alert(1)、data:text/html,<script></script> 完全无效。你把它塞进 <a href="%7B%7B.URL%7D%7D"></a> 或 <img src="%7B%7B.Src%7D%7D"> 里,照样执行。
- 只适用于纯文本插入 HTML 内容区场景,比如
<p>{{.Text}}</p> - 用在属性值(
href、src、onclick)里?必须加协议白名单校验,拒绝javascript:、data:、vbscript: - 用在
<script></script>标签内部?绝对禁止字符串拼接,改用json.Marshal输出到data-属性再读取 - 模板里写
{{.Raw | safeHTML}}?等于主动关掉防护——上游没过滤干净,XSS 就进来了
template.HTML 是“信任开关”,不是“过滤开关”
html/template 默认会对 {{.Field}} 自动转义,这是安全基线;但一旦你包一层 template.HTML(userInput),就等同于告诉模板:“这串 HTML 我已确认安全”。可如果用户提交的是 <img src="x" onerror="alert(1)">,它就原样上屏。
- 仅对经 bluemonday 等成熟库白名单过滤后的 HTML 使用
template.HTML - 过滤逻辑必须提到 handler 层,不能丢给模板做判断
- 避免在模板中出现
{{.Content | safeHTML}}—— 模板不该承担内容净化责任 - 哪怕用了
template.HTML,输出时仍需走html/template渲染,不能fmt.Fprintf(w, ...)裸输出
富文本必须用 bluemonday,别信正则清洗
有人写正则删 on\w+= 或 javascript:,但绕过方式太多:onmousemove=alert(1)//、JaVaScRiPt:、javascript: 全都能逃逸。正则不是 HTML 解析器,没法处理嵌套、编码、大小写混用。
- 安装:
go get github.com/microcosm-cc/bluemonday - 用
bluemonday.UGCPolicy(),不是StrictPolicy—— 后者会干掉<strong></strong>、<ul></ul>等常用标签 - 示例:
p := bluemonday.UGCPolicy(); clean := p.Sanitize(input) - 过滤后的内容,再传给模板时仍要走
{{.CleanHTML | safeHTML}},且确保该变量类型是template.HTML
HTTP 头和 CSP 是补丁,不是替代方案
设置 X-Content-Type-Options: nosniff 防止 MIME 嗅探,加 Content-Security-Policy: default-src 'self' 限制脚本加载源,这些都很有用,但它们发生在浏览器端,无法阻止恶意 HTML 已被注入并渲染成功。
- CSP 对内联脚本(
<script>...</script>)、eval、内联事件(onclick)有强约束,但前提是服务端没把危险内容直接吐出来 - API 返回 JSON 时,必须设
Content-Type: application/json; charset=utf-8,否则某些旧浏览器可能误解析为 HTML - 所有响应头应在中间件统一设置,避免每个 handler 重复写,也防止遗漏
href 属性?每个环节的编码/过滤策略都不同,漏掉一个,前面全白做。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











