在进行SCA本地扫描或者ScanCentral打包翻译的时候,经常会碰到翻译阶段卡住不动的情况,这时候就要知道该从翻译日志的哪些报错信息开始查起。首先要明白,Fortify的翻译阶段本身并不等同于漏洞扫描,它实际上是通过sourceanalyzer工具,把源代码、配置文件或者构建命令,转换成和build ID绑定在一起的中间数据,等到后续的扫描阶段,才会再以这些中间文件作为基础,去生成最终的FPR结果。按照官方文档的解释,Translation这个步骤就是把源代码转成跟build ID关联的中间格式,然后Analysis阶段再去扫描那些已经识别出来的文件,并产生对应的结果文件。
一、翻译阶段老是卡住的原因
当Fortify的翻译过程卡在那里不动的时候,我们不要一上来就断定是工具本身出了故障,因为有不少情况,其实是项目的原始构建还没有真正跑完、依赖包拉取的时候被卡住了、某个文件递归处理得太深,或者是当前的build ID里面混进了之前留下来的旧数据。
1、原始的构建命令自己就没能正常结束
像Java、Gradle、Maven、MSBuild、Make这些类型的项目,如果在不套Fortify的情况下,直接去跑mvn clean package、gradle build、msbuild或者make这些命令都会卡住,那么在前面加上sourceanalyzer以后,它当然也同样会卡住。比较妥当的做法是先脱离Fortify的环境,单独把这些构建命令执行一遍,等到确认项目的构建能够顺利结束了,再把sourceanalyzer给加上去。
2、依赖或者运行环境没有提前准备好
在对普通的需要编译的项目做翻译时,需要保证构建所要用到的那些依赖都已经就绪了,官方文档里面也提醒过,翻译这个步骤通常是需要项目构建所依赖的那些东西的,而不同的语言还会有各自具体的要求。如果访问代码仓库、私有服务器、JDK、SDK、编译器、npm源或者NuGet源的时候出现了异常,那么从日志上看,就好像是Fortify卡住了一样,可实际上程序是在那里等着这些依赖或者编译工具响应。
3、扫描时圈定的范围太大,或者目录选错了
假如在翻译的时候,把node_modules、target、build、dist目录,还有第三方的SDK、压缩包解压出来的文件夹、历史的备份目录,这些都一股脑儿地给纳入了进来,那就会把整个任务的速度给明显拖慢。这种情况在前端项目和混合类型的项目里尤其常见,一旦选择的路径不小心指向了仓库的上一级目录,Fortify就会去处理一大堆根本不相关的文件。
4、build ID没能及时清理
要是反复去使用同一个build ID,但上一次翻译留下来的数据却没有被清掉的话,后面再产生的文件列表和配置,就很有可能跟前一次的混到一起去。在官方给出的示例里面也建议过,在准备拿一个已经用过的build ID去分析项目之前,应该先去执行一下sourceanalyzer-b MyProject-clean这条命令。
二、翻译日志里应该优先查看哪些报错信息
在排查翻译阶段的问题时,首先要去看的是所执行的命令、日志存放的路径,还有产生的warnings警告,而不要只盯着日志的最后一行去猜。按照OpenText支持文章里的说法,排查的时候是需要提供实际执行的那条命令的,而默认的日志存放位置,在Windows系统里是用户目录下的AppDataLocalFortifysca<版本号>log,在非Windows系统里则是用户home目录下的.fortify/sca<版本号>/log,而且他们还建议在运行的时候启用-debug选项,以便收集更多的调试信息。
1、先去检查那些无法解析类和符号的报错
在Java的日志里头,经常能够看到像Unable to resolve type、Unable to resolve function、Unable to locate import、Unable to resolve symbol这一类的提示。官方文档里面专门把这些Java翻译时的警告给列了出来,并且也说明了,可以用sourceanalyzer-b
2、检查文件有没有被正确地收录进来
我们可以跑一下sourceanalyzer-b
3、留意内存和超时这类的提示
要是在日志里面看到了out of memory、GC overhead、heap space、timeout、permission denied、path too long这些信息,就得先去把运行环境的问题给解决好。这个时候,可以试着去增加SCA的内存参数,把翻译的范围给缩小一些,或者是将整个项目的路径搬到一个更短、更干净的目录下面去。
三、怎么减少翻译阶段卡住带来的返工
等到翻译阶段的运行稳定下来了以后,就需要把相关的配置给固化到流水线脚本里面去,而不是每一次都靠人工临时去调整命令。
1、把构建的入口固定下来
对于Maven、Gradle、MSBuild、Make这些类型的项目,应该统一去使用项目实际的构建入口。官方文档里面也提供了把sourceanalyzer放在Gradle、MSBuild、Make等构建命令之前进行集成的方式,同时它也支持借助compile_commands.json这个文件,来翻译C和C++的项目。
2、把需要排除的目录固定下来
最好是把依赖的缓存目录、构建产生的输出目录、测试生成的目录、第三方库的目录,还有备份用的目录,都写进排除规则里面去,这样做的话,翻译这个阶段就不会因为每次无关的文件变得越来越多,而把速度给拖得越来越慢了。
3、要把排查问题所需的材料保留好
每次碰到翻译卡住的情况时,都应当把当时完整的命令、build ID、日志、执行的时间、项目的分支、JDK或者编译器的版本、依赖源当时的状态,还有机器的资源截图,这些统统保存下来。不要只是截一张写着“正在翻译”的图片,因为管理员和厂商的技术支持,是需要靠这些详细的信息,才能判断出问题到底是出在构建上、环境上,还是SCA本身的配置上。
总结
要弄清楚Fortify的翻译阶段为什么会频繁卡住,以及翻译日志里应该优先去看哪些报错信息,排查的时候一般可以按照这样的顺序来:首先去确认一下原始的构建过程能不能独立完成,然后再依次去检查依赖环境、扫描时圈定的范围、build ID有没有被清理,还有日志里跳出来的那些警告。在看日志的时候,要重点关注那些无法解析类和符号的提示、关键文件有没有被正确纳入build ID、内存超时和权限方面的错误。等把问题处理完之后,还要记得把构建的入口、要排除的目录、日志的输出方式,还有-clean的清理规则,都作为固定的配置给确定下来,这样翻译阶段才不会老是卡在同一种类型的问题上。