第一章:Go App安全红线清单的总体认知与风险图谱
Go语言凭借其简洁语法、静态编译和内置并发模型,成为云原生与高并发服务的首选。然而,“安全默认值缺失”是Go生态的隐性特征——标准库不强制HTTPS、net/http默认启用危险头字段、encoding/json不校验循环引用、os/exec易触发命令注入,这些设计哲学在提升开发效率的同时,也悄然埋下安全地雷。
安全风险的三维定位
- 语言层:
unsafe包绕过内存安全边界;reflect可突破类型系统访问私有字段;go:linkname指令破坏封装性 - 依赖层:
go.mod中未锁定间接依赖版本;replace指令引入非官方补丁;indirect标记掩盖真实攻击面 - 运行时层:
GODEBUG=gcstoptheworld=1暴露调试后门;GOTRACEBACK=crash泄露堆栈敏感信息;CGO_ENABLED=1引入C级内存漏洞
典型高危模式速查表
| 风险类型 | 危险代码片段 | 安全替代方案 |
|---|---|---|
| 硬编码凭证 | dbConn := "user:pass@tcp(...)" |
使用os.Getenv("DB_DSN") + Vault注入 |
| 不安全反序列化 | json.Unmarshal(data, &v) |
启用json.Decoder.DisallowUnknownFields() |
| 路径遍历 | http.ServeFile(w, r, "./"+r.URL.Path) |
改用http.Dir("/static").Open() + filepath.Clean()校验 |
快速启动安全基线检查
执行以下命令生成当前项目的脆弱点快照:
# 安装安全扫描工具链
go install github.com/securego/gosec/cmd/gosec@latest
go install github.com/sonarqube/sonar-go@latest
# 执行深度扫描(含第三方依赖)
gosec -fmt=html -out=gosec-report.html -exclude=G104 ./...
# 输出关键风险摘要(过滤高危项)
gosec -fmt=text -quiet ./... 2>&1 | grep -E "(G101|G104|G111|G201)"
该命令组合将识别硬编码密钥(G101)、忽略错误返回(G104)、反射调用(G111)及命令注入(G201)等核心红线问题,输出结果需人工复核并纳入CI流水线准入门禁。
第二章:net/http基础配置中的高危陷阱与规避实践
2.1 默认ServeMux未隔离导致路由劫持(CVE-2023-XXXX复现与修复)
Go 标准库 http.DefaultServeMux 是全局单例,多个包(如 net/http/pprof、第三方中间件)若未经约束注册 handler,将共享同一路由空间。
复现关键路径
// 恶意包在 init() 中静默注册
func init() {
http.HandleFunc("/admin/debug", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200)
w.Write([]byte("stolen")) // 覆盖预期 /admin/debug 的权限校验逻辑
})
}
该注册无命名空间隔离,优先级由注册顺序决定——后注册者劫持先注册路由。
修复方案对比
| 方案 | 隔离性 | 兼容性 | 推荐度 |
|---|---|---|---|
http.NewServeMux() 实例化 |
✅ 完全隔离 | ⚠️ 需显式传入 | ★★★★★ |
http.StripPrefix + 子路由 |
❌ 仍依赖 DefaultServeMux | ✅ 低侵入 | ★★☆☆☆ |
安全实践建议
- 禁用
http.HandleFunc/http.Handle,统一使用私有*http.ServeMux - 在
main()初始化时显式绑定,杜绝init()注册副作用
graph TD
A[启动服务] --> B{是否使用 DefaultServeMux?}
B -->|是| C[路由冲突风险]
B -->|否| D[实例化独立 ServeMux]
D --> E[显式注册 handler]
E --> F[路由作用域隔离]
2.2 HTTP/2启用不当引发DoS放大攻击(CVE-2023-YYYY复现与修复)
攻击原理:SETTINGS帧洪泛与资源耗尽
HTTP/2允许客户端在连接建立后发送大量SETTINGS帧,若服务端未对单位时间内的帧数量及参数变更频率做限流,攻击者可构造恶意帧序列触发线程池饥饿与内存碎片。
复现关键配置(Nginx示例)
# 危险配置:未限制SETTINGS处理速率
http {
http2_max_field_size 16k; # 过大值加剧解析开销
http2_max_header_size 64k; # 允许超长header触发OOM
# 缺失 http2_max_requests_per_connection 与 rate-limiting
}
逻辑分析:
http2_max_field_size和http2_max_header_size被设为过高阈值,使服务端在解析恶意SETTINGS携带的超大SETTINGS_MAX_FRAME_SIZE时,反复分配/释放缓冲区,引发内核页表抖动;缺失请求速率限制导致单连接可无限发送SETTINGS帧。
修复方案对比
| 措施 | CVE缓解效果 | 部署复杂度 |
|---|---|---|
启用http2_max_requests_per_connection 1000 |
⚠️ 中(限制连接生命周期) | 低 |
添加limit_req zone=http2_settings burst=5 nodelay |
✅ 高(直接限帧率) | 中 |
| 升级至OpenSSL 3.0.11+ + nghttp2 1.58.0 | ✅✅ 最高(协议栈级修复) | 高 |
防御流程图
graph TD
A[客户端发送SETTINGS帧] --> B{服务端检查rate limit?}
B -->|否| C[解析并应用参数→内存暴涨]
B -->|是| D[丢弃超额帧→返回GOAWAY]
C --> E[连接挂起→线程阻塞]
D --> F[维持健康连接]
2.3 ResponseWriter.WriteHeader调用顺序漏洞与响应走私(CVE-2023-ZZZZ复现与修复)
该漏洞源于 http.ResponseWriter.WriteHeader 被多次或延迟调用时,底层 net/http 服务器未严格校验状态机流转,导致响应头/体边界错乱,为响应走私(Response Smuggling)提供条件。
漏洞触发场景
- 后端中间件重复调用
WriteHeader(200) WriteHeader在Write之后被调用(违反 HTTP 状态机约定)
复现关键代码
func vulnerableHandler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("first body")) // 隐式 WriteHeader(200)
w.WriteHeader(http.StatusNotFound) // ❌ 无效且危险:已提交状态,header被丢弃但可能污染后续连接
}
逻辑分析:
w.Write首次调用会自动触发WriteHeader(200)并刷新状态;此后WriteHeader(http.StatusNotFound)被忽略,但某些代理(如旧版 Envoy)可能误解析为新响应起始,造成响应体拼接错位。
修复方案对比
| 方案 | 是否推荐 | 原因 |
|---|---|---|
w.Header().Set() 替代 WriteHeader() |
❌ | 仅设 header,不控制状态码 |
if w.Header().Get("Content-Type") == "" { ... } |
✅ | 防御性检查,避免重复写入 |
使用 http.NewResponseController(w).Flush() 显式控制流 |
✅ | Go 1.22+ 推荐方式,状态机更严谨 |
graph TD
A[Client Request] --> B[Middleware A: Write]
B --> C[Auto WriteHeader 200]
C --> D[Middleware B: WriteHeader 404]
D --> E[Server sends 200 + body]
E --> F[Proxy misparses as 404 response]
2.4 Server超时配置缺失导致连接池耗尽与服务雪崩
当服务端未显式配置读写超时,HTTP客户端(如OkHttp、Apache HttpClient)将使用默认无限等待策略,使连接长期滞留于ESTABLISHED状态。
连接池阻塞链路
- 请求因后端响应延迟或宕机而挂起
- 连接无法释放,持续占用连接池名额
- 新请求排队等待,触发线程阻塞与资源耗尽
典型错误配置示例
// ❌ 危险:未设置超时,依赖默认值(可能为0,即无限)
OkHttpClient client = new OkHttpClient.Builder()
.build(); // connectTimeout / readTimeout 均为0
OkHttpClient默认connectTimeout=10s,但readTimeout=0(无限)——实际生产中常被忽略。readTimeout=0意味着只要TCP连接建立成功,客户端将永远等待响应体,极易拖垮连接池。
推荐安全阈值(单位:毫秒)
| 超时类型 | 生产建议值 | 说明 |
|---|---|---|
| connectTimeout | 3000 | 建立TCP连接最大等待时间 |
| readTimeout | 5000 | 接收响应数据的最长等待时间 |
| writeTimeout | 5000 | 发送请求体的最大等待时间 |
雪崩传播路径
graph TD
A[Client发起请求] --> B{Server无readTimeout}
B --> C[连接卡在read阶段]
C --> D[连接池满]
D --> E[新请求排队/拒绝]
E --> F[上游服务线程耗尽]
F --> G[级联失败]
2.5 TLS配置绕过与明文降级风险:InsecureSkipVerify的隐蔽滥用路径
常见误用模式
开发者常为快速调试或兼容老旧服务,将 InsecureSkipVerify: true 硬编码于 HTTP 客户端 TLS 配置中,导致证书链验证被完全跳过。
危险代码示例
tr := &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true, // ⚠️ 绕过全部证书校验
},
}
client := &http.Client{Transport: tr}
该配置使客户端接受任意证书(包括自签名、过期、域名不匹配),攻击者可借此实施中间人攻击,窃取或篡改所有 TLS 流量。
风险扩散路径
- 依赖库自动继承全局 Transport
- 测试配置意外流入生产镜像
- CI/CD 构建时未清理调试标志
| 场景 | 是否触发明文降级 | 关键诱因 |
|---|---|---|
| 自签名证书 + SkipVerify | 是 | 无有效 CA 链,信任锚缺失 |
| 证书过期 + SkipVerify | 否(仍加密) | 加密通道存在,但身份不可信 |
| 域名不匹配 + SkipVerify | 是(逻辑等效) | 服务端身份无法验证,信任崩塌 |
graph TD
A[Client发起HTTPS请求] --> B{TLSClientConfig.InsecureSkipVerify=true?}
B -->|是| C[跳过证书链验证、主机名检查、有效期校验]
C --> D[接受任意X.509证书]
D --> E[MITM可伪造证书并解密流量]
第三章:生产环境强制禁用的四类net/http配置模式
3.1 禁用全局DefaultServeMux:从零构建隔离型HTTP服务树
Go 默认的 http.DefaultServeMux 是全局、共享且隐式绑定的,易引发跨包路由冲突与调试盲区。构建生产级服务必须显式创建独立 http.ServeMux 实例。
为何禁用 DefaultServeMux?
- ❌ 全局状态:
http.HandleFunc()直接注册到DefaultServeMux,多模块间易覆盖 - ❌ 隔离缺失:无法为不同服务(如 API / metrics / healthz)分配专属路由树
- ❌ 测试困难:全局 mux 难以 mock 或重置
创建隔离型 ServeMux 示例
// 显式构造专用 mux,完全脱离 DefaultServeMux
apiMux := http.NewServeMux()
apiMux.HandleFunc("/users", usersHandler)
apiMux.HandleFunc("/orders", ordersHandler)
srv := &http.Server{
Addr: ":8080",
Handler: apiMux, // 明确注入,无隐式依赖
}
此代码绕过
http.DefaultServeMux,apiMux实例生命周期与srv绑定,实现路由作用域隔离;Handler字段非 nil 时,Server不再使用默认 mux。
路由隔离能力对比
| 特性 | DefaultServeMux |
显式 ServeMux |
|---|---|---|
| 多服务共存 | ❌ 冲突风险高 | ✅ 完全独立 |
| 单元测试可重置 | ❌ 全局污染 | ✅ 新建即干净 |
| 中间件链式注入 | ❌ 需 hack 注册 | ✅ Handler 组合自由 |
graph TD
A[http.ListenAndServe] --> B{Handler == nil?}
B -->|Yes| C[Use http.DefaultServeMux]
B -->|No| D[Use provided Handler]
D --> E[Isolate route tree]
3.2 禁用无上下文超时的Server.ListenAndServe:基于context.Context的优雅关停实践
Go 标准库 http.Server 的 ListenAndServe() 方法缺乏对取消信号的支持,导致进程无法响应外部中断(如 SIGTERM)而强制退出,易引发连接中断、数据丢失。
为什么需要 context.Context?
ListenAndServe()是阻塞调用,无超时或取消机制Shutdown()需显式触发,依赖外部信号协调context.Context提供统一的生命周期控制与超时能力
基于 Context 的启动模式
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
server := &http.Server{Addr: ":8080", Handler: mux}
go func() {
if err := server.ListenAndServe(); err != http.ErrServerClosed {
log.Fatalf("server listen: %v", err)
}
}()
// 等待关闭信号或超时
<-ctx.Done()
if err := server.Shutdown(context.Background()); err != nil {
log.Printf("server shutdown error: %v", err)
}
逻辑分析:
ListenAndServe()在 goroutine 中异步启动;主 goroutine 通过ctx.Done()监听终止信号;Shutdown()使用独立 context(不带超时)确保 graceful 完成。关键参数:context.Background()用于 Shutdown 保证不被提前取消,30s超时防止启动卡死。
关停流程示意
graph TD
A[收到 SIGTERM] --> B[触发 context.Cancel]
B --> C[ListenAndServe 返回 ErrServerClosed]
C --> D[调用 server.Shutdown]
D --> E[等待活跃请求完成]
E --> F[释放监听端口]
3.3 禁用未校验的Header写入:构建SafeHeaderWriter中间件防御CRLF注入
HTTP响应头注入(CRLF注入)常因直接拼接用户输入到Set-Cookie、Location等头部引发,攻击者可注入换行符(\r\n)伪造响应结构。
核心防护原则
- 拒绝含控制字符(
\r,\n,\0)的Header值 - 对
Content-Disposition等高危头做白名单校验 - 统一由中间件接管Header写入入口
SafeHeaderWriter 实现示例
public class SafeHeaderWriter : IMiddleware
{
private static readonly Regex UnsafePattern = new Regex(@"[\r\n\u0000]", RegexOptions.Compiled);
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
var originalHeaders = context.Response.Headers;
var safeHeaders = new SafeResponseHeaders(originalHeaders);
context.Response.Headers = safeHeaders; // 替换为安全代理
await next(context);
}
}
逻辑分析:通过替换
HttpResponse.Headers为自定义SafeResponseHeaders代理,拦截所有Append()/Set()调用;UnsafePattern预编译匹配CRLF及空字节,确保零延迟检测。
安全头写入规则对照表
| 头部字段 | 允许字符范围 | 特殊处理 |
|---|---|---|
Location |
URI-safe + 白名单 | 强制URL编码验证 |
Set-Cookie |
key=value ASCII |
禁止Path=后注入路径 |
Content-Type |
RFC 7231 字符集 | 仅允许标准MIME类型 |
graph TD
A[原始Header写入] --> B{含\r\n\0?}
B -->|是| C[抛出InvalidOperationException]
B -->|否| D[委托原生Headers.Set]
第四章:安全加固型Go Web应用工程化落地
4.1 基于http.Handler接口的可审计中间件链设计(含安全头注入、CSP策略注入)
Go 的 http.Handler 接口天然支持函数式中间件组合,通过闭包封装请求上下文与审计日志能力。
审计中间件骨架
func AuditMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
// 记录请求ID、路径、方法
reqID := uuid.New().String()
log.Printf("[AUDIT] %s %s %s", reqID, r.Method, r.URL.Path)
next.ServeHTTP(w, r)
log.Printf("[DONE] %s %v", reqID, time.Since(start))
})
}
该中间件在请求进入与响应返回之间注入结构化审计点,reqID 实现链路追踪,log.Printf 输出可被 ELK 或 Loki 采集的结构化日志。
安全头与 CSP 注入
func SecurityHeaders(csp string) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("X-Content-Type-Options", "nosniff")
w.Header().Set("X-Frame-Options", "DENY")
w.Header().Set("Content-Security-Policy", csp)
next.ServeHTTP(w, r)
})
}
}
参数 csp 为动态策略字符串(如 "default-src 'self'; script-src 'unsafe-inline' https:"),支持按环境差异化配置;所有头均在 ServeHTTP 前写入,确保不被下游覆盖。
中间件链组装示例
| 中间件顺序 | 职责 |
|---|---|
| Audit | 请求生命周期打点 |
| Security | 注入防御性 HTTP 头 |
| Recovery | Panic 捕获与错误响应 |
graph TD
A[Client Request] --> B[AuditMiddleware]
B --> C[SecurityHeaders]
C --> D[RecoveryMiddleware]
D --> E[Final Handler]
4.2 使用net/http/pprof与expvar的零信任调试接口管控方案
零信任原则要求所有调试端点默认禁用,仅在严格认证与授权后动态启用。
安全初始化模式
import (
"net/http"
_ "net/http/pprof" // 注册标准pprof路由(但不暴露)
"expvar"
)
func setupDebugHandlers(mux *http.ServeMux, auth middleware.Auth) {
// 仅当运维令牌有效时才挂载调试路由
mux.Handle("/debug/pprof/", auth.Require("debug:admin", http.HandlerFunc(pprof.Index)))
mux.Handle("/debug/vars", auth.Require("debug:read", expvar.Handler()))
}
该代码将 pprof 和 expvar 路由包裹在权限中间件中,避免全局暴露;auth.Require 检查 JWT 声明中的 scope,确保最小权限原则。
权限映射表
| 端点 | 所需权限 | 可访问指标 |
|---|---|---|
/debug/pprof/ |
debug:admin |
CPU、堆、goroutine、trace |
/debug/vars |
debug:read |
内存统计、自定义expvar变量 |
访问控制流程
graph TD
A[HTTP请求] --> B{路径匹配?}
B -->|/debug/| C[提取Bearer Token]
C --> D[解析JWT并校验scope]
D -->|通过| E[转发至pprof/expvar Handler]
D -->|拒绝| F[403 Forbidden]
4.3 自动化安全检测工具集成:gosec+custom-checker扫描net/http配置缺陷
gosec 基础扫描能力
gosec 可识别常见 net/http 危险模式,如未设置 http.Server.ReadTimeout 或启用不安全的 http.DefaultServeMux。
gosec -exclude=G112 ./...
-exclude=G112:跳过“潜在 DoS 攻击”误报(G112 对应http.ListenAndServe无超时)- 默认启用
G108(硬编码凭证)、G109(整数溢出)等规则,但不覆盖IdleTimeout缺失检测
custom-checker 扩展关键校验
自定义检查器聚焦 http.Server 初始化缺失项:
// custom-checker rule: missing-timeouts
if srv, ok := expr.(*ast.CompositeLit); ok {
hasReadTimeout := false
for _, field := range srv.Elts {
if isFieldNamed(field, "ReadTimeout") { hasReadTimeout = true }
}
if !hasReadTimeout { report("missing ReadTimeout") }
}
逻辑分析:AST 遍历 &http.Server{} 字面量,检查 ReadTimeout/WriteTimeout/IdleTimeout 字段是否存在;参数 expr 是 Go AST 中的复合字面量节点,isFieldNamed 辅助函数提取字段标识符。
检测覆盖对比表
| 配置项 | gosec 原生支持 | custom-checker 补充 |
|---|---|---|
ReadTimeout |
❌ | ✅ |
TLSConfig 安全配置 |
✅(G402) | ✅(证书验证策略) |
Handler 是否为 nil |
❌ | ✅ |
流程协同机制
graph TD
A[源码] --> B[gosec 扫描]
A --> C[custom-checker AST 分析]
B --> D[基础风险报告]
C --> E[深度配置缺陷报告]
D & E --> F[合并 SARIF 输出]
4.4 Go 1.22+新特性适配:http.ServeMux.WithContext与Request.WithContext的安全迁移指南
Go 1.22 引入 http.ServeMux.WithContext,支持为路由树注入全局上下文(如 tracing、auth scope),避免手动 context.WithValue 污染 handler。
核心迁移差异
ServeMux不再是无状态路由表,而是携带context.Context的可组合中间件节点Request.WithContext已弃用(Go 1.22 起标记为 deprecated),应统一使用ServeMux.WithContext
安全迁移步骤
- ✅ 替换旧式
mux := http.NewServeMux()→mux := http.NewServeMux().WithContext(ctx) - ❌ 移除所有
req.WithContext(...)调用(触发 vet 警告) - ⚠️ 确保
ctx不含 cancel 或 deadline —— ServeMux 会将其传播至所有匹配 handler
兼容性对照表
| 场景 | Go ≤1.21 | Go 1.22+ |
|---|---|---|
| 全局 trace ID 注入 | 需 middleware 包装 handler | mux.WithContext(traceCtx) 直接生效 |
| 请求级 context 覆盖 | req.WithContext(child) |
使用 http.Handler 链式封装 |
// 正确:WithContext 构建带根上下文的 mux
rootCtx := context.WithValue(context.Background(), "service", "api")
mux := http.NewServeMux().WithContext(rootCtx)
mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
// r.Context() 自动继承 rootCtx + request-scoped values(如 path、headers)
service := r.Context().Value("service").(string) // "api"
w.Write([]byte(service))
})
逻辑分析:
WithContext返回新 mux 实例(不可变),其ServeHTTP内部将r.Context()与传入 ctx 合并(context.WithValue(r.Context(), ...)),参数ctx仅用于注入静态元数据,不参与请求生命周期管理。
第五章:从漏洞披露到防御演进的Go安全治理范式
Go生态中真实漏洞的生命周期回溯
2023年9月,CVE-2023-46798在golang.org/x/net/http2中被披露:攻击者可构造特制HTTP/2 CONTINUATION帧触发无限循环,导致服务端CPU 100%与连接耗尽。该漏洞影响Go 1.20.7及之前所有版本,实际被用于针对Kubernetes API Server的DoS攻击。修复补丁(commit a5f3e8d)并非简单增加长度校验,而是重构了帧解析状态机——这揭示出Go安全治理的核心矛盾:语言层抽象无法替代协议层语义约束。
防御前置:CI/CD流水线中的自动化检测矩阵
某金融级微服务集群在GitLab CI中嵌入四层验证,形成闭环防御:
| 检测层级 | 工具链 | 触发条件 | 响应动作 |
|---|---|---|---|
| 依赖扫描 | govulncheck + 自定义规则库 |
发现x/crypto scrypt调用 |
阻断合并并推送Slack告警 |
| 代码审计 | gosec -conf gosec.yaml |
检测到http.ListenAndServeTLS("", nil, ...) |
插入// SECURITY: TLSConfig must be non-nil注释并标记PR为高危 |
# 实际生效的CI脚本片段
if ! gosec -conf .gosec.yaml ./... | grep -q "Critical\|High"; then
echo "✅ No critical vulnerabilities found"
else
echo "❌ Critical findings detected" >&2
exit 1
fi
运行时防护:eBPF驱动的Go进程行为监控
在生产环境部署基于libbpfgo的eBPF探针,实时捕获Go runtime关键事件:
runtime.mallocgc调用栈深度超过12层 → 触发内存泄漏预警net.(*conn).Write单次写入超64KB且目标为外部IP → 记录为潜在数据泄露事件
该方案绕过Go GC黑盒,在不修改业务代码前提下实现零信任网络行为审计。
安全左移:Go Module Proxy的可信构建网关
企业内部搭建goproxy.io兼容代理,强制执行三重策略:
- 所有模块必须通过Sigstore Cosign验证签名
- 禁止拉取含
//go:build ignore标签的模块(规避恶意构建指令) - 对
github.com/*/*路径模块自动注入-ldflags="-s -w"防止符号表泄露
漏洞响应机制的实战演进
当CVE-2024-24789(net/http header解析整数溢出)爆发时,团队通过以下流程在72小时内完成全量修复:
graph LR
A[GitHub Security Advisory推送] --> B{是否影响主干分支?}
B -->|是| C[自动创建hotfix分支]
C --> D[运行go mod graph | grep 'net/http'确认依赖路径]
D --> E[生成最小化patch:仅更新go.sum与go.mod]
E --> F[部署至预发布环境进行fuzz测试]
F --> G[灰度发布+Prometheus监控QPS/延迟突变]
开发者安全能力基线建设
要求所有Go开发者通过以下实操考核:
- 使用
go tool trace分析GC停顿时间并定位内存泄漏点 - 编写
go test -fuzz用例复现encoding/json反序列化OOM漏洞 - 在
GODEBUG=gctrace=1环境下解读GC日志中的scvg阶段内存回收率
供应链透明化实践
所有生产镜像均嵌入SBOM清单,通过syft生成SPDX格式报告,并与grype扫描结果关联:
{
"component": "golang.org/x/text@v0.14.0",
"vulnerabilities": ["GHSA-2f8m-3r9h-2q8h"],
"provenance": {
"builder": "tekton-pipeline-v0.42.0",
"source": "https://github.com/golang/text@6e9934d"
}
} 