用 Go 优雅地清理 HTML 并抵御 XSS——Bluemonday

news2025/4/24 4:30:40

1、背景与动机

只要你的服务接收并回显用户生成内容(UGC)——论坛帖子、评论、富文本邮件正文、Markdown 等——就必须考虑 XSS(Cross‑Site Scripting)攻击风险。浏览器在解析 HTML 时会执行脚本;如果不做清理,恶意用户可插入 <script>onerror 等内容窃取 Cookie 或劫持会话。

Bluemonday 的使命就是 “先 allowlist,后输出”:只留下安全允许的元素与属性,其余一律剥离,保证最终字符串对浏览器“无害”。

2、XSS 攻击原理与防线简述

攻击类型触发机理常见载体
反射型恶意片段拼进 URL,服务器原样输出搜索框、重定向链接
存储型恶意脚本写入数据库,其他用户浏览时触发论坛帖子、评论
DOM 型前端 JS 对外部数据拼接 innerHTMLJSONP、模板拼接

综合防御思路

  1. 输入校验:长度、格式、白名单字符集。
  2. 输出编码/清理:HTMLEscape、CSP、Bluemonday 等。
  3. 最小权限:Cookie HttpOnly/SameSite、前后端分离降低风险。

3、认识 Bluemonday

3.1 主要特性

  • 纯 Go 实现;零 CGo 依赖,可用在任意平台。
  • 基于允许列表(Allowlist);默认拒绝一切未知元素,安全系数高。
  • 多种预置策略StrictPolicyUGCPolicyNewPolicy() 自定义。
  • 线程安全:Policy 对象是只读,可被多个 goroutine 并发复用。
  • 支持 string/[]byte/io.Reader 三种输入形式,便于流式处理。citeturn0search1

3.2 安装与版本管理

go get github.com/microcosm-cc/bluemonday@latest

Bluemonday 发布节奏相对稳定,建议在 go.mod 中锁定次版本号(v1.x.y)以避免潜在破坏性变更。

4、快速上手:StrictPolicy 一键剥离标签

最“硬核”的策略就是全部移除标签,仅保留文本

policy := bluemonday.StrictPolicy()
clean  := policy.Sanitize(`<p>Hello <strong>世界</strong>!<script>alert(1)</script></p>`)
// clean == "Hello 世界!"

该策略实现了 “硬删除脚本 + 去掉所有属性” 的极致安全;在 Markdown‑>HTML 渲染前做一次清理,可有效杀死脚本注入。citeturn0search0

5 、进阶使用:UGCPolicy 与自定义策略

5.1 UGCPolicy——保留安全富文本

StrictPolicy 虽安全,却也太“干净”。当你需要 保留 <a><em><ul> 等常用排版元素 时,可以使用官方预设的 UGCPolicy()

p   := bluemonday.UGCPolicy()
out := p.Sanitize(`<a href="http://evil.com" onclick="steal()">点我</a>`)
fmt.Println(out)
// <a href="http://evil.com" rel="nofollow">点我</a>

重点:

  • 允许 <a>、自动加 rel="nofollow"
  • 过滤一切 JS‑相关属性onclick, onerror 等)。
  • 自动修正不完整/畸形标签,防跳脱闭合漏洞。citeturn0search2

5.2 手写自定义 Policy

如果业务场景需要 保留特定 CSS class、data-* 自定义属性,可通过 NewPolicy() 自定义:

p := bluemonday.NewPolicy()

// 允许 block/inline 常用元素
p.AllowElements("p", "ul", "li", "strong", "em")

// 允许 <a>,但仅开放 href=https://* 并加 rel="noopener"
p.AllowAttrs("href").Matching(bluemonday.UrlRegexp).OnElements("a")
p.RequireNoFollowOnLinks(false)
p.AddTargetBlankToFullyQualifiedLinks(true)

// 允许 <span class="highlight">
p.AllowAttrs("class").Matching(regexp.MustCompile(`^(highlight)$`)).OnElements("span")

// …更多颗粒度设置

Bluemonday 的 API 链式可读性高;官方文档中每个 Allow* 方法都带示例,可参考并组合。

6、性能、并发与内存开销

  • 并发安全:Policy 初始化后为只读结构体,可在全局变量缓存并被 goroutine 复用。
  • 基于标准库 html Tokenizer:解析成本≈ O(n),常规博文(~5 KB)清理耗时 < 100 µs。
  • 零分配策略SanitizeBytes 复用切片,避免多余 copy。

性能调优要点:

  1. 单例化 Policy,避免每次请求都 NewPolicy()
  2. 对高并发流量可用 sync.Pool 复用临时缓冲区,减轻 GC 压力。

7、与 Gin 集成的落地示例

// middleware/htmlsan.go
var htmlPolicy = bluemonday.UGCPolicy()

func SanitizeHTML() gin.HandlerFunc {
    return func(c *gin.Context) {
        if c.Request.Method == http.MethodPost || c.Request.Method == http.MethodPut {
            // 读 body
            raw, _ := io.ReadAll(c.Request.Body)
            clean := htmlPolicy.SanitizeBytes(raw)

            // 重写 body 并继续链路
            c.Request.Body = io.NopCloser(bytes.NewReader(clean))
            c.Request.ContentLength = int64(len(clean))
        }
        c.Next()
    }
}

注册:

r := gin.Default()
r.Use(middleware.SanitizeHTML())
  • 适用于 富文本编辑器上传评论接口 等写操作。
  • 若上传为 JSON,可在绑定结构体前使用 json.Decoder + htmlPolicy.Sanitize() 逐字段过滤。

8、单元测试与安全基线

func TestStripXSS(t *testing.T) {
    cases := []struct{
        in, out string
    }{
        {`<img src=x onerror=alert(1)>`, ``},
        {`<a href="javascript:alert(1)">x</a>`, `<a rel="nofollow">x</a>`},
    }

    p := bluemonday.UGCPolicy()
    for _, c := range cases {
        if got := p.Sanitize(c.in); got != c.out {
            t.Errorf("want %q, got %q", c.out, got)
        }
    }
}
  • 建议将常见 XSS Payload 集合(OWASP Cheat Sheet)纳入回归测试。
  • 关注安全通报:例如 Go‑2022‑0588 提及自定义策略允许 style 时可能触发 CSS XSS,应尽量避免。

9、常见陷阱 & 优化建议

场景潜在风险建议
盲目 AllowElements("style")CSS 注入绕过使用 CSP 并限制 style
文件上传富文本嵌入 <img src="data:…">内嵌恶意 SVG限制 src 协议为 https
前端再拼接 innerHTML += …DOM XSS前端使用 textContent 或框架安全输出
大文件批量清理内存飙升使用 SanitizeReader 流式处理

10、 结语

Bluemonday 把复杂的 XSS 防御落地成本降到了“引一个包 + 三行代码”
然而安全永远不是“一招鲜”:

  • 输入校验、输出清理、浏览器 CSP 缺一不可。
  • 单元测试 & 安全扫描 持续跟进新 Payload。
  • 合理选择 StrictPolicy / UGCPolicy / 自定义混合策略,平衡 用户体验安全强度

把好内容入口关,让你的 Go Web 服务拥有“消毒后”的纯净输入!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2341205.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

window上 elasticsearch v9.0 与 jmeter5.6.3版本 冲突,造成es 启动失败

[2025-04-22T11:00:22,508][ERROR][o.e.b.Elasticsearch ] [AIRUY] fatal exception while booting Elasticsearchjava.nio.file.NoSuchFileException: D:\Program Files\apache-jmeter-5.6.3\lib\logkit-2.0.jar 解决方案&#xff1a; 降低 es安装版本 &#xff0c;选择…

【C++初阶】第15课—模版进阶

文章目录 1. 模版参数2. 模版的特化2.1 概念2.2 函数模版特化2.3 类模板特化2.3.1 全特化2.3.2 偏特化 3. 模版的分离和编译4. 总结 1. 模版参数 模版参数分为类型形参和非类型参数之前我们写过的大量代码&#xff0c;都是用模版定义类的参数类型&#xff0c;跟在class和typena…

黑阈免激活版:智能管理后台,优化手机性能

在使用安卓手机的过程中&#xff0c;许多用户会遇到手机卡顿、电池续航不足等问题。这些问题通常是由于后台运行的应用程序过多&#xff0c;占用大量系统资源导致的。今天&#xff0c;我们要介绍的 黑阈免激活版&#xff0c;就是这样一款由南京简域网络科技工作室开发的手机辅助…

Mujoco robosuite 机器人模型

import ctypes import os# 获取当前脚本所在的目录 script_dir os.path.dirname(os.path.abspath(__file__))# 构建库文件的相对路径 lib_relative_path os.path.join(dynamic_models, UR5e, Jb.so)# 拼接成完整的路径 lib_path os.path.join(script_dir, lib_relative_path…

K8s:概念、特点、核心组件与简单应用

一、引言 在当今云计算和容器技术蓬勃发展的时代&#xff0c;Kubernetes&#xff08;简称 K8s&#xff09;已成为容器编排领域的事实标准。它为管理容器化应用提供了高效、可靠的解决方案&#xff0c;极大地简化了应用的部署、扩展和运维过程。无论是小型初创公司还是大型企业…

STM32的定时器输出PWM时,死区时间(DTR)如何计算

在 STM32F429&#xff08;以及所有 STM32F4 “高级定时器”&#xff09;中&#xff0c;死区时间由 TIMx_BDTR 寄存器的 8 位 “Dead‑Time Generator” 字段 DTG[7:0] 来配置。其计算分三步&#xff1a; 计算死区时钟周期 tDTS TIM1 时钟源为 APB2 定时器时钟&#xff08;PCL…

STC32G12K128单片机GPIO模式SPI操作NorFlash并实现FatFS文件系统

STC32G12K128单片机GPIO模式SPI操作NorFlash并实现FatFS文件系统 NorFlash简介NorFlash操作驱动代码文件系统测试代码 NorFlash简介 NOR Flash是一种类型的非易失性存储器&#xff0c;它允许在不移除电源的情况下保留数据。NOR Flash的名字来源于其内部结构中使用的NOR逻辑门。…

ClickHouse 设计与细节

1. 引言 ClickHouse 是一款备受欢迎的开源列式在线分析处理 (OLAP) 数据库管理系统&#xff0c;专为在海量数据集上实现高性能实时分析而设计&#xff0c;并具备极高的数据摄取速率 1。其在各种行业中得到了广泛应用&#xff0c;包括众多知名企业&#xff0c;例如超过半数的财…

智能体MCP 实现数据可视化分析

参考: 在线体验 https://www.doubao.com/chat/ 下载安装离线体验 WPS软件上的表格分析 云上创建 阿里mcp:https://developer.aliyun.com/article/1661198 (搜索加可视化) 案例 用cline 或者cherry studio实现 mcp server:excel-mcp-server、quickchart-mcp-server

再看开源多模态RAG的视觉文档(OCR-Free)检索增强生成方案-VDocRAG

前期几个工作提到&#xff0c;基于OCR的文档解析RAG的方式进行知识库问答&#xff0c;受限文档结构复杂多样&#xff0c;各个环节的解析泛化能力较差&#xff0c;无法完美的对文档进行解析。因此出现了一些基于多模态大模型的RAG方案。如下&#xff1a; 【RAG&多模态】多模…

深入浅出 NVIDIA CUDA 架构与并行计算技术

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《深度探秘&#xff1a;AI界的007》 &#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、CUDA为何重要&#xff1a;并行计算的时代 2、NVIDIA在…

FPGA系列之DDS信号发生器设计(DE2-115开发板)

一、IP核 IP(Intellectual Property)原指知识产权、著作权等&#xff0c;在IC设计领域通常被理解为实现某种功能的设计。IP模块则是完成某种比较复杂算法或功能&#xff08;如FIR滤波器、FFT、SDRAM控制器、PCIe接口、CPU核等&#xff09;并且参数可修改的电路模块&#xff0c…

【Dv3Admin】从零搭建Git项目安装·配置·初始化

项目采用 Django 与 Vue3 技术栈构建&#xff0c;具备强大的后端扩展能力与现代前端交互体验。完整实现了权限管理、任务队列、WebSocket 通信、系统配置等功能&#xff0c;适用于构建中后台管理系统与多租户平台。 本文章内容涵盖环境搭建、虚拟环境配置、前后端部署、项目结…

P3416-图论-法1.BFS / 法2.Floyd

这道题虽然标签有floyd但是直接bfs也能过 其实事实证明还是bfs快&#xff0c;因为bfs只需要遍历特定的点&#xff0c;但是floyd需要考虑遍历所有可能的中介点 法1.BFS 用字典存储每个点所能普及的范围&#xff0c;然后用对每个点bfs进行拓展 nint(input())temp[]#xmax0;yma…

极狐GitLab 议题和史诗创建的速率限制如何设置?

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;关于中文参考文档和资料有&#xff1a; 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 议题和史诗创建的速率限制 (BASIC SELF) 速率限制是为了控制新史诗和议题的创建速度。例如&#xff0c;如果您将限制设置为 …

提交到Gitee仓库

文章目录 注册配置公钥创建空白的码云仓库把本地项目上传到码云对应的空白仓库中 注册 注册并激活码云账号&#xff08; 注册页面地址&#xff1a;https://gitee.com/signup &#xff09; 可以在自己C盘/用户/用户名/.ssh 可以看到 有id_rsa.pub 以前在GitHub注册时搞过&…

oracle中错误总结

oracle中给表起别名不能用as&#xff0c;用as报错 在 Oracle 数据库中&#xff0c;​​WITH 子句&#xff08;即 CTE&#xff0c;公共表表达式&#xff09;允许后续定义的子查询引用前面已经定义的 CTE​​&#xff0c;但 ​​前面的 CTE 无法引用后面的 CTE​​。这种设计类似…

纽约大学具身智能体在城市空间中的视觉导航之旅!CityWalker:从海量网络视频中学习城市导航

作者&#xff1a;Xinhao Liu, Jintong Li, Yicheng Jiang, Niranjan Sujay, Zhicheng Yang, Juexiao Zhang, John Abanes, Jing Zhang, Chen Feng单位&#xff1a;纽约大学论文标题&#xff1a;CityWalker: Learning Embodied Urban Navigation from Web-Scale Videos论文链接&…

OpenCV颜色变换cvtColor

OpenCV计算机视觉开发实践&#xff1a;基于Qt C - 商品搜索 - 京东 颜色变换是imgproc模块中一个常用的功能。我们生活中看到的大多数彩色图片都是RGB类型的&#xff0c;但是在进行图像处理时需要用到灰度图、二值图、HSV&#xff08;六角锥体模型&#xff0c;这个模型中颜色的…

Manus技术架构、实现内幕及分布式智能体项目实战

Manus技术架构、实现内幕及分布式智能体项目实战 模块一&#xff1a; 剖析Manus分布式多智能体全生命周期、九大核心模块及MCP协议&#xff0c;构建低幻觉、高效且具备动态失败处理能力的Manus系统。 模块二&#xff1a; 解析Manus大模型Agent操作电脑的原理与关键API&#xf…