buffalo框架默认不自动转义模板变量,{{ .name }}会原样输出用户输入,若为"alert(1)"则直接执行js,导致xss;必须显式用{{ html .name }}或{{ .name | html }}转义,且不同上下文需用attr/js/urlquery等专用函数。

Buffalo 框架默认不自动 HTML 转义模板变量,必须显式调用转义函数,否则极易引发 XSS。
为什么 {{ .Name }} 不安全?
Buffalo 使用 html/template 底层,但其模板语法(如 {{ .Name }})默认**不转义**——这和 Go 标准库的 html/template 行为相反。它把转义责任完全交给开发者,而非默认防护。
- 如果
.Name = "<script>alert(1)</script>",{{ .Name }}会原样输出并执行 - 只有
{{ html .Name }}或{{ .Name | html }}才触发转义 - 该设计源于早期 Buffalo 为兼容性牺牲安全性,至今未改默认行为
{{ html .Input }} 和 {{ .Input | html }} 有区别吗?
没有本质区别,两者都调用内置 html 函数,效果一致。但要注意:
Buffalo框架 1.0.1 版本源码包下载,适合需要错误处理改进、依赖更新、render.Download 注释和 request logger 调整的 v1 项目。
-
{{ html .Input }}更直观,推荐用于单值转义 -
{{ .Input | html }}支持链式过滤,比如{{ .Input | html | truncate 50 }} - 不能混用:
{{ html .Input | truncate }}会报错,因为html返回的是template.HTML类型,而truncate期望字符串 - 所有用户输入渲染到 HTML 上下文时,必须包裹
html,哪怕只是显示在<div> 里 <h3>哪些场景容易漏掉转义?</h3> <p>最常踩坑的是属性值、JS 内联、CSS 和 URL 上下文,<code>html函数只适用于 HTML 元素体(body context),不适用于其他上下文:<div title="{{ html .Title }}"> ❌ 错误:title 属性需要属性上下文转义,<code>html不够用-
<script>var name = "{{ html .Name }}";</script>❌ 危险:JS 字符串需 JS 转义,不是 HTML 转义 -
<a href="/user?id=%7B%7B%20.ID%20%7D%7D"></a>❌ 若.ID含&,会破坏 URL 结构 - 正确做法:用专用函数,如
{{ .Title | attr }}(属性)、{{ .Name | js }}(JS 字符串)、{{ .ID | urlquery }}(URL 参数) - 统一约定团队模板规范,例如「所有
{{ .xxx }}必须带过滤器」 - 禁用原始输出:
{{ raw .Content }}只允许在白名单组件中使用,并加代码审查注释 - 用静态检查工具(如
buffalo-generate插件或自定义 AST 扫描)识别未转义的{{ .Var }} - 对富文本内容,不要用
html,改用safe+ 白名单 HTML 解析器(如bluemonday)
自定义转义函数能替代内置方案吗?
可以,但没必要自行实现 HTML 转义逻辑。Buffalo 的
html函数底层就是调用html.EscapeString,已足够安全。重点应放在:真正难的不是怎么转义,而是记住「Buffalo 从不替你兜底」——每个
{{ }}都是潜在入口,漏一个就可能被绕过。










