html/template默认可防绝大多数xss,因其上下文感知自动转义;而html.escapestring仅转义5个字符且仅适用于纯文本插入,无法防护属性、url、js等上下文中的xss。

html/template 默认就能防住绝大多数 XSS,前提是别主动绕过它——比如用 text/template、手动拼 HTML、或滥用 template.HTML。
为什么 html.EscapeString 不能当 XSS 防护主力
html.EscapeString 只转义 、<code>>、"、'、& 这 5 个字符,对 javascript:alert(1)、onerror=alert(1)、data:text/html,<script></script> 完全无效。
它只适用于纯文本插入 HTML 内容区的场景,比如:<p>{{.Text}}</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2525" title="Go语言(Golang)1.26.0"><img
src="https://img.php.cn/upload/manual/001/589/237/6a6adeed24a4a355.png" alt="Go语言(Golang)1.26.0" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/gongju/2525" title="Go语言(Golang)1.26.0" class="overflowclass">Go语言(Golang)1.26.0</a>
<p class="overflowclass">Go语言(Golang)1.26.0版本官方下载,版本号 1.26.0,适合旧项目维护、兼容性测试和指定版本开发环境搭建。</p>
</div>
<a rel="nofollow" href="/xiazai/gongju/2525" title="Go语言(Golang)1.26.0" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>。
一旦用错位置,风险立刻暴露:
- 塞进
href或src属性?必须额外校验协议(拒绝javascript:、data:、vbscript:) - 拼进
<script></script>内部?绝对禁止字符串拼接;应改用json.Marshal输出到data-属性再读取 - 用在
onclick="..."里?漏引号或未 JSON 编码,可能直接导致语法错误 + 绕过
用错模板引擎:text/template 是静默炸弹
text/template 不做任何转义,用户输入什么就原样输出什么。
常见错误写法:
-
import "text/template"+template.New("").Parse(...) - 手动拼接 HTML 字符串:
fmt.Fprintf(w, "<div>"+userInput+"</div>") - 在 handler 中用
strings.ReplaceAll“消毒”后再塞给模板——这反而破坏了html/template的上下文感知转义逻辑
正确做法只有一条:
- 明确导入
"html/template" - 所有动态内容统一走
{{.Field}}插入,让模板自己判断该在哪转义、怎么转义
富文本怎么办:别信正则,用 bluemonday
用户能发带格式的评论或文章?不能靠 template.HTML 伪装安全,必须先过滤 DOM 树。
正则清洗是陷阱:
- onmousemove=alert(1)//、JaVaScRiPt:、javascript%3A 全都能逃逸
- 正则不是 HTML 解析器,处理不了嵌套、编码、大小写混用、注释干扰
实战建议:
- 安装:
go get github.com/microcosm-cc/bluemonday - 用
bluemonday.UGCPolicy()(不是StrictPolicy,后者会干掉<strong></strong>、<ul></ul>等常用标签) - 过滤后的内容再传给模板:
{{.CleanHTML | safeHTML}},且确保变量类型是template.HTML - 注意:过滤必须在 handler 层完成,不能丢给模板做判断
CSP 和响应头只是补丁,不是防护核心
X-XSS-Protection 已被 Chrome 78+、Firefox 76+、Edge 80+ 全面弃用,Safari 从未支持,删掉这类代码。
真正该配的是 Content-Security-Policy,例如:default-src 'self'; script-src 'self' 'unsafe-inline'。
但记住:CSP 发生在浏览器端,它拦不住已成功注入并渲染的恶意 HTML;它只能阻止后续执行。
所以最易被忽略的一点是:**所有防护都建立在「输出时走 html/template 渲染」这个前提上**。哪怕用了 bluemonday 和 CSP,如果某处裸调 fmt.Fprintf 或误用 text/template,整套防线就从根上断了。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










