近期,笔者接到一个任务,因为代码安全原因,需要批量升级一系列的Golang第三方组件,这里面包含了直接引用的第三方库和间接引用的第三方库,其中第三方库也包括能够直接升级和不能直接升级两种,这里把相关解决方案沉淀在此,供大家参考
首先,随着Golang语言的火热,不论是官方还是开发者都越来越重视其中的安全问题,Golang安全团队在2023年也发布了govulncheck的1.0.0版本,而在业界,也有一些比较好的扫描工具可以用比如trivy。
不论是哪一种静态扫描或镜像扫描工具,都会给出一系列的官方引用库的修复指引,这时候,很多开发者发现,事情其实没有者这么简单,直接引用的还好,根据修复指引和漏洞信息找到对应的版本就好,间接引用的版本,由于涉及到第三方库自身的升级,这里需要操作的步骤比较多,而且有的第三方库可能没有最新的release版本,这个是否如何进行安全的升级变成了一个问题,这里就把几种升级方式进行分享。
首先,在岁月静好的一天,作为研发的你,发现了一个了不起的漏洞扫描软件trivy,经过研发,你发现它可以直接扫描仓库代码进行漏洞扫描,尝试扫描项目后,结果如下:
啊,原来代码中引用的Gin版本太低了,存在漏洞,需要升级,怎么操作呢?
你从修复指引中了解到,需要将Gin从1.8.1升级到1.9.0版本,那么,你很自然的在Golang项目中查找go.mod文件,看看直接引用库Gin的版本:
发现确实是1.8.1,说明项目确实直接引用Gin库需要升级,那怎么找到可以升级的版本呢?
当然,在这个示例中,trivy漏洞指引中已经告诉你需要升级1.9.0release版本,所以可以直接跳过第二步,笔者这里主要针对没有直接列出可修复release版本的情况
一种方法是去库对应的官网,比如在Gin的官网得知1.9.0是一个release版本
还有一种方法比较快捷的方式:
在go.mod同级目录下,执行:
go list -m -mod=mod -u all
这个命令会列出所有直接引用库以及它们的版本,并且会标出哪些包需要升级。
上图中括号里面显示的是,可以升级的最新release版本### 3.进行升级
使用以下命令来升级:
go get -u
这样就可以将直接引用的有release版本的第三方库进行升级
至此,我们通过对直接引用的GIn库进行升级.修复了安全漏洞
然后当你再用trivy工具进行扫描时,发现问题并没有解决:
这里我们以trivy工具扫描的结果为示例
Gin的1.8.1的问题还在
这时,你决定对整个项目进行搜索,发现在go.sum文件中存在对Gin的1.8.1版本的引用
你发现,事情没有这个简单了
再回到这个扫描结果
这里我们以trivy工具扫描的结果为示例
你观察到,有的引用库是一个SHA信息,有的引用库有两个SHA信息
比如上图的1.8.1只有一个哈希值,而1.9.1有两个哈希值,这是为什么?
原来,go.sum
的存在的意义在于:希望别人或者在别的环境中构建当前项目时所使用引用库跟 go.sum
中记录的是完全一致的,从而达到一致构建的目的。
如果在go.mod
记录了一个引用库,则在go.sum
文件中则会记录引用库的哈希值(同时还有引用库中 go.mod 的哈希值)
反过来,如果只有一个哈希值,说明这个引用库是个间接引用库
参考资料:https://my.oschina.net/renhc/blog/3171035
答案是:go mod graph
这个命令会列出所有直接和间接依赖项之间的依赖关系。你可以在这个列表中查找你要升级的包,并找到直接或间接依赖它的包。然后,你可以查看这些包的版本,看看它们是否需要升级。
例如上图,可以看到,X/text是gin1.9.1版本的引用库
而下图则显示,cors库引用了gin的1.8.1:
当然,这里的引用关系比较多,看控制台数据会比较不直观,特别是层层引用的情况。这里推荐一个可视化的工具gmchart
安装方式
go get -u github.com/PaulXu-cn/go-mod-graph-chart/gmchart
使用方式
go mod graph | gmchart
它会生成一个html的引用依赖图:
这样就可以看层层的引用关系了
通过上面两个图,发现原来有来两个库的gin版本是1.8.1,一个是gin-contrib/cors,另一个是swaggo/gin-swagger
下面我们来看看,怎么升级这两个引用库
首先看cors库, 通过go list -m -mod=mod -u all
命令,发现cors并没有可升级的release版本
去git上找下最近release版本是不是没有收录
果然已经是最新的release
不慌,这个时候,还有机会,可以去源代码处找下最新代码:
恩,最新代码改了,只不过没有发布release版本,这个时候,可以把源代码下载下来,直接引用
go mod tidy
和go mod vender
其中,go mod tidy
的作用是自检一下修改go.mod文件是否正确;
go mod vendor
则基于go.mod文件生成vendor, 即下载对应的内容
执行完后,查看vendor文件夹下的modules.txt文件,看下修改是否生效
上图则表示,生效了!
go build
看下是否编译通过即可!
cors引用库的问题解决了
那么开始解决swagger引用库的问题
通过go list -m -mod=mod -u all
命令,发现没有可以升级的包了
去git上找下最近release版本和最新的master代码
swagger最新的代码,也只是将gin升级到了1.9.0
不是漏洞扫描要求的1.9.1
这…就得动源码了。。。
go mod tidy
和go mod vender
其中,go mod tidy
的作用是自检一下修改go.mod文件是否正确;
go mod vendor
则基于go.mod文件生成vendor, 即下载对应的内容
执行完后,查看vendor文件夹下的modules.txt文件,看下修改是否生效
上图则表示,生效了!
go build
看下是否编译通过即可!