静态分析过程中遇到的开源代码缺陷应该如何处理?
之前我们分析了想要获得准确有价值的静态分析结果,需要编译过程的介入。
然而,现代的软件开发过程引入了大量的开源代码,参与编译的代码/工件并不全是自研的,软安SCA工具在一次对单体车机系统的完整扫描过程中,发现在约100G的项目中,有6500+的开源组件需要被治理,从代码占比的角度来说,80%以上的代码都是由开源部分构成。
本质上来说,不论自研或是开源,都会作为源代码参与到静态分析的过程;于是,就产生了这样一个非常实际的问题:如果静态分析工具发现缺陷出现在开源组件,或由于开源组件引起,那我作为开源软件的使用方,是否需要对其做修复呢?
在回答这个问题之前,我们不妨先来探讨几个针对开源软件的问题。
开源软件的归属与治理
Q1 开源软件属于谁?
我们以1024当天开源的AutoSAR项目小满(https://easyxmen.atomgit.com)为例解释一下这里的关系;在开源之前,“小满”的前身是普华商业版的安全车控操作系统,归属权毫无疑问属于普华基础软件公司。
在2024年10月24日之后,普华将“小满”捐献给了开放原子基金会,这意味着从这天开始,“小满”正式归属于开源基金会;同时,从性质上来说,普华此刻就变成了和全球所有贡献者一样的角色,共同建设“小满”项目。
唯一区别是,作为捐赠者和最具备经验的贡献方,普华还主动承担着为该项目提供技术支持,代码贡献,社区运营等工作,并在项目的发展和决策过程中发挥较大的影响力。
Q2 开源软件代码质量相对自研软件,更好还是更差?
根据软件工程领域的"Many Eyes"效应(用来描述开源软件项目中的现象,即代码的缺陷更有可能被大量贡献者发现和修复,因为有更多的“眼睛”在审查和使用代码),越热门的开源项目, 往往代码质量会相对越高。
实际上根据软安静兮SAST工具对诸多开源项目的扫描结果,以Openssl为例,该观点一定程度上得到印证,Openssl项目平均每千行代码缺陷密度在0.5左右,即使放在一个CMMI5等级的软件企业中,也是非常高水平的存在。
Q3 开源软件出了安全问题或者功能不满足的情况,作为使用方一般怎么处理?
通常企业不会主动招惹开源软件的“问题”,基本上都是跟踪开源软件本身是否有安全漏洞,如果有就优先寻求补丁,或者通过外围手段规避该漏洞,只有在没有其他方案的前提下,会考虑升级开源软件到无漏洞版本甚至自己动手。至于功能不满足,呵呵,要什么自行车啊?
Q4 开源软件的功能版本迭代有规律可循吗?
“典型”的开源软件(排除基于开源版本提供的商业发行版)基本没有对发版频率的约束,功能方面通常也不会像商业版软件那样有明确的短期/长期Roadmap。至于如何决定新功能,通俗来讲常见的方式有用户需求反馈,社区投票,商业赞助,核心开发主导等方式。
基于上面几个问题,我们可以得出这样一个阶段性结论:开源软件看起来是非常普遍,由别人提供的,但质量却相当不错;没什么“保障”,似乎还有些潜在风险的存在。
静态分析中的开源代码缺陷处理
下面回到我们最初的问题,开源组件的问题,管不管?
我们用ROS2(一个被广泛使用于自动驾驶领域的开源项目)做例子,来模拟一下实际情况。
我们首先使用软安静兮SAST工具扫描ROS2项目:

在问题列表页面,我们随机查看一些严重问题:

点击某一问题编号,通过查看具体路径发现该问题来自于zstd_vendor目录下的某一文件:

与“研发”团队确认后,发现zstd_vendor并不是“自研”代码,于是我们使用软安SCA工具扫描ROS2项目(展示部分结果):

发现ROS2本身还包含一些开源组件,是的,开源组件也不一定是独立存在的,它们之间会有复杂的引用关系。
以ZSTD为例,该项目是Meta(原Facebook)的一个开源项目,在ROS2构建的过程中,作为功能的一部分,参与了编译。至此,我们确认了ZSTD是该项目中使用到的一个开源组件。

ZSTD不属于ROS2项目的“自研”代码。经过内部详细评估后,虽然问题确实存在,但考虑项目周期,“研发团队“决定先不对所有ZSTD的代码缺陷做任何处理。
推荐的操作方式有以下两种:
a 人工忽略所有该组件下曝出的问题,后续版本在展示问题时,会默认继承该操作,通过将“忽略”问题过滤掉,可以不再显示这些缺陷。

b 在提交缺陷到平台的过程中,通过正则表达式,排除ZSTD项目所在文件夹 ros2/build/zstd_vendor/,在提交之前就把该开源组件里的所有缺陷排除。
以上两种方案,前一种适合在全面排查问题时留下操作记录;后一种适合在快速CI/CD过程中,减少研发人员看到问题的时间消耗。
接下来我们再把精力放在ROS2“本身”的代码缺陷:
下面发现了一个严重的空指针解引用问题,标号指明了发生的一系列事件,在事件时间1中ptr_prev被赋值为0,当按照事件2,3,4,5,6,7,8路线执行,在事件9发生了pre_prev->next,对空指针ptr_prev解引用。

以下是一个资源泄露问题,在事件3调用opendir分配资源或者内存,当程序遵循箭头标识的事件顺序执行,到事件11时,直接return false了,没有释放分配给dir的资源。

上述方式无疑是最“务实”的处理方式。但与此同时,我们也知道开源代码也是软件项目的一部分,提升开源代码的可靠性同时也会提升自己产品的竞争力,本质上是所有使用方皆可获益的无私的利他行为,这跟狭义的商业逻辑似乎相违背,然而开源经济有其自己的商业逻辑,安卓,Linux,鸿蒙等项目的成功也给主导这些项目的商业机构带来了巨大的成功。
如果我们真的发现了开源代码的缺陷,或者就是想对开源代码的特性做一些完善甚至新增,那么应该怎么处理呢?
我们继续上面的例子,毕竟用到了ZSTD,希望该开源软件可靠性也能提升,但我又不想只有自己改动,这等于变相维护了一个只有我自己用的版本,且不提许可证是否允许我这么干,光是潜在的兼容性风险就不值得这么做。
如果ZSTD社区对此毫不知情,而我又不想在新版本里再遇到这个问题,那么最好的方法,就是去社区提交issue,希望开源组件的开发者能帮忙修复这个缺陷,一劳永逸。
软安科技在持续开发打磨静态分析工具的过程中,会用大量的开源软件作为测试对象,在这个过程中,我们会持续不断的向开源社区提交经过人工审核的严重缺陷。希望借此机会能够为开源软件的安全可靠贡献一份来自软安的力量。
(本文中所有例子都已经向社区提出issue)
有兴趣了解有关此主题的更多信息?您私信我们申请试用!
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)