Go防XSS核心是输出编码与上下文感知:html/template自动转义所有{{.Field}},富文本须用bluemonday白名单过滤后再转template.HTML,HTTP头和CSP仅为补位。

Go 语言防 XSS 的核心不是「输入过滤」,而是「输出编码 + 上下文感知」;盲目在入库前或传入模板前对用户输入做 HTML 标签清洗、正则替换,反而破坏安全机制,还可能引入新漏洞。
html/template 自动转义才是默认安全基线
只要用 html/template(不是 text/template),所有 {{.Field}} 插入都会按上下文自动转义:HTML 内容区、属性值、<script></script> 块、style 属性里,各自用不同规则处理。
- 错误写法:
import "text/template"→ 用户填<script>alert(1)</script>会原样输出 - 正确写法:
import "html/template",模板中直接写{{.Comment}},无需任何手动转义 - 别提前调用
html.EscapeString再传给模板——它只转 5 个字符(<、>、"、'、&),对javascript:、onerror=、data:text/html完全无效,且干扰模板的上下文判断
template.HTML 不是“过滤开关”,是“信任开关”
template.HTML 类型的作用是告诉 html/template:“这段字符串我已确认安全,别转义了”。它本身不做过滤、不验证、不消毒。
- 常见误用:
template.HTML(userInput)→ 用户提交<img src="https://img.php.cn/" alt="Go语言xss如何过滤_Go语言输入过滤使用方法【推荐】">就直接执行 - 正确路径:富文本必须先经
bluemonday白名单过滤,再包成template.HTML - 过滤后仍要走
{{.CleanHTML | safeHTML}}渲染,不能用fmt.Fprintf裸输出
富文本必须用 bluemonday,别信正则或自定义清洗
正则无法解析 HTML 结构,面对大小写混用(JaVaScRiPt:)、编码绕过(%6A%61%76%61%73%63%72%69%70%74:)、嵌套属性(onmouseover="foo()" onclick="bar()")完全失效。
立即学习“go语言免费学习笔记(深入)”;
- 安装:
go get github.com/microcosm-cc/bluemonday - 用
bluemonday.UGCPolicy(),不是StrictPolicy(后者会删掉<strong>、<ul>等常用标签) - 示例:
p := bluemonday.UGCPolicy(); clean := p.Sanitize(input) - 过滤后的
clean字符串,再传给模板时仍需显式标记为template.HTML类型
HTTP 头和 CSP 是补位,不是防线主体
X-Content-Type-Options: nosniff 和 Content-Security-Policy 在浏览器端生效,只能缓解已注入并渲染成功的恶意 HTML,无法替代服务端的输出编码。
- 设置
X-XSS-Protection已被现代浏览器弃用,不要依赖 - CSP 无法阻止
<img src=x onerror=...>这类内联事件执行,前提是 HTML 已被渲染 - 真正起效的第一道闸门,永远是 handler 层传入模板的数据是否经过上下文感知转义
最易被忽略的一点:所有非 HTML 输出场景(比如 JSON API、HTTP 响应体裸字符串、日志打印)都不受 html/template 保护,必须单独处理——JSON 接口用 json.Marshal,日志避免拼接用户输入,响应头加 Content-Type: application/json + X-Content-Type-Options: nosniff。


















