html/template 仅防html文本、双引号属性值、css内联样式、js字符串四类xss;对url上下文(如href=javascript:)、template.html类型、onxxx事件、style属性等不转义,需手动校验或安全函数处理。

html/template 的自动转义到底防住了哪些 XSS 场景
html/template 不是万能盾牌,它只在特定上下文做转义:变量插值到 HTML 文本节点、属性值(双引号内)、CSS 内联样式、JS 字符串字面量这四类场景下生效。比如 {{.Name}} 渲染成 <div>Alice</div> 时,Alice 里的 <script></script> 会被转成 <script>;但一旦你写成 <a href="https://www.php.cn/link/8627a5992a7f67f8c1e3db85cf9c23eb">link</a>,而 .URL 是 javascript:alert(1),它**不会**被拦截——因为 href 属于「URL 上下文」,html/template 默认不校验协议合法性。
什么时候自动转义会失效,必须手动干预
以下情况 html/template 完全不转义,交由开发者兜底:
- 使用
template.HTML类型包装的值(如template.HTML("<script>alert(1)</script>")) - 调用
printf "%s"或其他格式化函数后直接插入模板(绕过类型检查) - 把用户输入拼进
style属性或onxxx事件处理器里(例如onclick="{{.ClickHandler}}") - 动态生成
src、href、formaction等跳转类属性,且未用urlquery或自定义安全函数处理
这些位置不是“漏转义”,而是设计上就要求你明确声明信任——比如用 {{.URL | urlquery}} 或提前用 net/url.Parse 校验协议白名单。
常见误用:把 html/template 当成通用过滤器
有人把用户输入先塞进 html/template 渲染,再取结果当纯文本用,以为这样就“消毒”了。这是错的:
立即学习“go语言免费学习笔记(深入)”;
- 模板渲染结果是
[]byte,若后续拼接进 JS 字符串或 JSON 字段,仍可能触发执行(比如var name = "{{.Name}}";中.Name含"和\) - 同一份数据在不同上下文需要不同处理:HTML 内容用
html.EscapeString,JS 字符串用json.Marshal(输出带引号和转义),URL 参数用url.QueryEscape -
text/template完全不转义,混用会导致 XSS(比如生成邮件模板时误用text/template渲染 HTML 片段)
生产环境必须加的两道防线
仅靠 html/template 远不够:
- HTTP 响应头加上
Content-Security-Policy: default-src 'self',禁止内联脚本和未授权域名资源加载 - 所有用户可控的 URL、CSS、JS 片段,在进入模板前做白名单校验:比如
strings.HasPrefix(url, "https://") || strings.HasPrefix(url, "/"),拒绝javascript:、data:、vbscript:
最危险的不是没转义,而是你以为已经转义了,却在某个属性值或嵌套模板里悄悄绕过了上下文感知。










