引言:什么是SARIF?它的产生背景是什么?SARIF主要包含哪些内容?使用SARIF有哪些好处?
1. SARIF简介
SARIF(Static Analysis Results Interchange Format ,静态分析结果交换格式)是一种用于描述静态分析结果的规范,用于在不同工具之间交换和理解静态分析报告。它最初是为了满足Eclipse插件开发者的需求而设计的,现在也被广泛应用于其他静态代码分析工具中。目前SARIF 2.1.0 已经是OASIS标准。
Note:OASIS是一个致力于推动基于XML标准化的非盈利组织,其成员来自各个行业,旨在通过标准化改善业务流程的效率和可靠性。其制定的标准通常遵循最佳实践原则,并提供了一个认证程序来证明符合标准的系统或产品具有互操作性。OSIS推出了许多被广泛采用的标准,如高级消息队列协议(Advanced Message Queuing Protocol,AMQP),以及物联网常用的消息队列遥测传输协议(Message Queuing Telemetry Transport,MQTT)等。
2. 产生背景
SARIF的产生背景主要基于两个因素:一是静态代码分析工具之间的互操作性,二是为了标准化静态代码分析结果的描述。
2.1. 静态代码分析工具之间的互操作性
静态代码分析是一种在软件开发过程中,通过分析源代码来查找潜在错误和安全漏洞的技术。然而,不同的静态代码分析工具可能会产生不同的分析结果,这使得在不同的工具之间进行比较和交换分析结果变得困难。为了解决这个问题,需要有一种通用的方式来描述静态分析结果,使得不同的工具可以理解和交换彼此的分析报告。
2.2. 标准化静态代码分析结果的描述
SARIF提供了一种标准化的方式来描述静态分析结果,包括问题的类型、位置、严重程度等等。通过使用SARIF,静态代码分析工具的开发者可以更容易地将自己的工具集成到其他系统中,或者在不同的工具之间进行互操作。此外,通过使用SARIF,用户也可以更容易地理解和分析静态分析报告,从而更好地进行代码质量和安全性的管理。
Note:SARIF文件样例可以参考微软官方的SARIF教程,对应的Github地址https://github.com/microsoft/sarif-tutorials/tree/main/samples
3. 主要内容
3.1. 检测工具
主要明确了静态代码检测所用的工具及对应的版本信息,举例如下
"tool": {
"driver": {
"name": "Coverity",
"version": "1.2"
}
}
3.2. 检测规则
主要明确了静态代码检测所用的检测规则,包含了规则描述信息、路径等,举例如下
{
"ruleId": "TUT1002",
"message": {
"text": "A result in a source file."
},
"locations": [
{
"physicalLocation": {
"artifactLocation": {
"uri": "io/kb.c",
"uriBaseId": "SRCROOT",
"properties": {
"comment": "If REPOROOT is C:\\project, this file location resolves to C:\\project\\src\\io\\kb.c"
}
}
}
}
]
}
3.3. 检测内容
主要明确了静态代码检测对象信息,如代码路径,举例如下
"SRCROOT": {
"uri": "src/",
"uriBaseId": "REPOROOT",
"description": {
"text": "The r."
},
"properties": {
"comment": "SRCROOT is expressed relative to REPOROOT."
}
}
3.4. 检测结果
主要明确了静态代码检测扫描出的告警信息,包含规则信息,告警产生的位置信息,告警描述信息等,举例如下
"results": [
{
"ruleId": "TUT1001",
"message": {
"text": "Use of uninitialized variable."
},
"locations": [
{
"physicalLocation": {
"artifactLocation": {
"uri": "collections/list.h"
},
"region": {
"startLine": 25,
"startColumn": 8,
"snippet": {
"text": "add_core(ptr, offset, val)"
}
}
}
}
],
"codeFlows": [
{
"message": {
"text": "Path from declaration to usage."
},
"threadFlows": [
{
"locations": [
{
"importance": "essential",
"location": {
"message": {
"text": "Variable 'ptr' declared."
},
"physicalLocation": {
"artifactLocation": {
"uri": "collections/list.h"
},
"region": {
"startLine": 15,
"startColumn": 8,
"snippet": {
"text": "int* ptr;"
} }
},
"logicalLocations": [
{
"fullyQualifiedName": "collections::list::add"
}
]
}
},
{
"importance": "unimportant",
"location": {
"physicalLocation": {
"artifactLocation": {
"uri": "collections/list.h"
},
"region": {
"startLine": 18,
"startColumn": 8,
"snippet": {
"text": "offset = 0;"
}
}
},
"logicalLocations": [
{
"fullyQualifiedName": "collections::list::add"
}
]
}
},
{
"importance": "essential",
"location": {
"message": {
"text": "Uninitialized variable 'ptr' passed to method 'add_core'."
},
"physicalLocation": {
"artifactLocation": {
"uri": "collections/list.h"
},
"region": {
"startLine": 25,
"startColumn": 8,
"snippet": {
"text": "add_core(ptr, offset, val)"
}
}
},
"logicalLocations": [
{
"fullyQualifiedName": "collections::list::add"
}
]
}
}
]
}
]
},
{
"message": {
"text": "Alternate path from declaration to usage."
},
"threadFlows": [
{
"locations": [
{
"importance": "essential",
"location": {
"message": {
"text": "Variable 'ptr' declared."
},
"physicalLocation": {
"artifactLocation": {
"uri": "collections/list.h"
},
"region": {
"startLine": 15,
"startColumn": 8,
"snippet": {
"text": "int* ptr;"
} }
},
"logicalLocations": [
{
"fullyQualifiedName": "collections::list::add"
}
]
}
},
{
"importance": "unimportant",
"location": {
"physicalLocation": {
"artifactLocation": {
"uri": "collections/list.h"
},
"region": {
"startLine": 22,
"startColumn": 8,
"snippet": {
"text": "val = 0;"
}
}
},
"logicalLocations": [
{
"fullyQualifiedName": "collections::list::add"
}
]
}
},
{
"importance": "essential",
"location": {
"message": {
"text": "Uninitialized variable 'ptr' passed to method 'add_core'."
},
"physicalLocation": {
"artifactLocation": {
"uri": "collections/list.h"
},
"region": {
"startLine": 25,
"startColumn": 8,
"snippet": {
"text": "add_core(ptr, offset, val)"
}
}
},
"logicalLocations": [
{
"fullyQualifiedName": "collections::list::add"
}
]
}
}
]
}
]
}
}
]
想了解更多SARIF的规范细节,可以参阅官方200多页的PDF文档,点击获取。
4. 使用SARIF规范的好处
- 提高透明度:通过使用SARIF规范,各方可以更好地了解软件质量度量的各个方面,从而有助于做出更明智的决策。
- 促进协作:使用SARIF规范可以促进软件开发过程中的协作,因为各方可以更好地了解彼此的关注点和要求。
- 标准化数据交换:使用SARIF规范可以确保各方在交流和交换与软件质量度量相关的信息时使用相同的格式和标准,从而减少数据交换中的混乱和误解。
总之,SARIF是一种用于软件质量度量交换的格式化数据规范,旨在提供一个通用的方法,以便各方能够以一种统一和标准化的方式交流和交换与软件质量度量相关的信息。它有助于提高透明度、促进协作和标准化数据交换,从而有助于在整个软件开发过程中实现更好的协作、沟通与决策。
5. 参考
[1] https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=sarif
[2] https://github.com/microsoft/sarif-tutorials