go的html/template默认通过上下文感知自动转义防xss,但需避免误用text/template、滥用template.html、漏引号或未校验跳转属性;富文本须先经bluemonday过滤再转template.html,csp仅作补位。

Go 的 html/template 默认就能防住绝大多数 XSS,前提是别在关键环节主动绕过它——比如把没过滤的用户输入包成 template.HTML、用 text/template 渲染、或在 JS 字符串里漏掉引号。
必须用 html/template,不能用 text/template
html/template 会根据插入位置(HTML 内容区、属性值、<script></script> 内部等)自动做上下文敏感转义;text/template 完全不处理,拼进去什么就输出什么。
- 错误写法:
import "text/template"+t, _ := template.New("t").Parse(...)→ 恶意输入如<script>alert(1)</script>会被原样输出 - 正确写法:
import "html/template",变量一律用{{.Field}}插入,不要手动拼 HTML 字符串 - 模板中禁止出现
{{.Raw | safeHTML}}这类调用——过滤逻辑不该丢给模板判断
html.EscapeString 只适用于纯文本插入场景
html.EscapeString 只转义 、<code>>、"、'、& 这 5 个字符,对 javascript:、onerror=、data:text/html 等完全无效。
- 能用:用户昵称填进
<p>{{.Name}}</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/6a6ae8334dfb7907.jpg" 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版本提供 Go 官方 Windows amd64 MSI 安装包下载入口,版本号 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>,此时html.EscapeString足够 - 不能用:用户填的链接塞进
<a href="%7B%7B.Url%7D%7D"></a>→ 必须额外校验协议(拒绝javascript:、data:) - 更不能用:拼进
<script>var url = "{{.Url}}";</script>→ 不加引号或未 JSON 序列化会导致语法错误甚至绕过
富文本必须先过 bluemonday,再转 template.HTML
允许用户发带格式的评论或文章?不能靠 template.HTML 伪装安全,必须用白名单过滤器清理 DOM 树。
- 安装:
go get github.com/microcosm-cc/bluemonday - 用
bluemonday.UGCPolicy(),不是StrictPolicy(后者会干掉<strong></strong>、<ul></ul>) - 过滤必须在 handler 层完成:
clean := bluemonday.UGCPolicy().Sanitize(input),再传给模板并显式转为template.HTML(clean) - 绝不能自己写正则删
on\w+=或<script></script>—— 大小写混用、HTML 注释、编码嵌套都能逃逸
CSP 是补丁,不是替代方案
即使所有模板和过滤都做对了,CSP 仍要配。但它拦不住已成功注入并渲染的恶意 HTML,只负责阻止执行。
- 基础配置:
w.Header().Set("Content-Security-Policy", "default-src 'self'; script-src 'self'") - 必须配合
Content-Type: text/html和X-Content-Type-Options: nosniff,否则浏览器可能 MIME 嗅探后执行 - 开发期可用
Content-Security-Policy-Report-Only收集违规日志,避免误杀正常 JS - 别依赖
<meta http-equiv="Content-Security-Policy">—— 它不适用于fetch、Web Worker 等场景
最容易被忽略的是上下文错位:比如在 <script></script> 里插值却忘了加引号,或把 URL 放进 href 却没校验协议。这些地方 html/template 虽然做了转义,但无法替你判断语义是否合法。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










