XSS防御必须按上下文精准转义:HTML文本用html.EscapeString,模板用{{.Data}}而非|safe,JS中用json.Marshal,URL需encodeURIComponent,禁用内联事件,配合CSP与HttpOnly Cookie。

直接在 Fiber 中写 ctx.SendString 或拼接 HTML 返回,不加处理就渲染用户输入,等于主动给攻击者开后门。XSS 防御不能靠“尽量不拼接”,而要靠明确上下文、明确转义、明确隔离。
HTML 输出时必须用 html.EscapeString 或模板自动转义
Fiber 本身不内置 HTML 转义函数,但 Go 标准库的 html.EscapeString 是最轻量可靠的方案。只要用户输入内容会插入到 HTML 文本节点或属性值中(比如 <div>{{.UserInput}}</div>),就必须转义。
- 不要自己写正则替换
<、>、"、'、&—— 容易漏掉边界情况(如编码) - 使用
html.EscapeString(input)是唯一推荐的纯文本转义方式;它覆盖全部 HTML 实体安全场景 - 若用
html/template渲染页面(推荐),确保变量用双大括号{{.UserInput}},而非{{.UserInput | safeHTML}}—— 后者绕过转义,仅限你 100% 确认内容可信时才用 - 注意:
text/template不做 HTML 转义,误用会导致漏洞;必须显式切换为html/template
JavaScript 上下文中禁止拼接用户输入到 script 标签或内联事件
DOM 型 XSS 最常出现在 JS 里把 URL 参数、API 返回字段直接塞进 eval()、innerHTML、location.href 或 onclick="doSomething('<code>userInput')" 这类位置。
- 绝对避免:
ctx.SendString(fmt.Sprintf(`<script>console.log("%s")</script>`, userInput)) - 正确做法:将数据作为 JSON 注入页面(用
json.Marshal序列化),再在前端用JSON.parse()读取 —— Go 的json.Marshal会自动对字符串中的引号、反斜杠、控制字符做转义 - 如果必须动态生成 JS 代码(极不推荐),至少用
js.EscapeString处理字符串,但它只适用于 JS 字符串字面量上下文,不适用于 JS 代码执行上下文(如eval) - 禁用所有内联事件绑定(
onclick、onerror),改用addEventListener+ 数据分离
设置 Content-Security-Policy 响应头拦截未授权脚本
CSP 是最后一道防线,能阻断大部分反射型和 DOM 型 XSS 的实际危害,即使页面被注入了 <script> 标签,浏览器也不会执行。
- 在 Fiber 中全局添加中间件:
app.Use(func(c *fiber.Ctx) error { c.Set("Content-Security-Policy", "default-src 'self'; script-src 'self' 'unsafe-inline'"); return c.Next() }) - 生产环境务必移除
'unsafe-inline'和'unsafe-eval';改用nonce或哈希白名单(例如script-src 'self' 'sha256-xxx...') - 配合
script-src 'self',可阻止加载外域恶意 JS;加上base-uri 'none'防止<base href>劫持相对路径 - 注意:CSP 不是替代输出编码的方案,而是叠加防御;没做转义 + 开放 CSP,依然可能触发 DOM 操作型漏洞
Cookie 必须设 HttpOnly + Secure + SameSite
即使发生 XSS,设对 Cookie 属性能让攻击者无法窃取会话凭证 —— 这是最容易被忽略却成本最低的加固点。
- Fiber 中设置 Session Cookie 时,显式传参:
cookie := &fiber.Cookie{HTTPOnly: true, Secure: true, SameSite: fiber.CookieSameSiteStrictMode} -
HttpOnly阻止document.cookie读取,使 XSS 获取不到 session_id -
Secure强制只通过 HTTPS 传输,防止明文泄露 -
SameSite=Strict或Lax可缓解 CSRF,也间接降低 XSS 辅助攻击链(如 XSS + 自动提交表单)的成功率
真正难的不是选哪个函数,而是每次往 HTML、JS、URL、CSS 任一上下文插入用户数据前,都得问一句:“这个值最终会在哪解析?按什么规则解析?”—— 答案不同,转义方式就完全不同。漏掉一个上下文,整套防护就形同虚设。


















