自定义规则集
- 引入于 13.5 版本。
- 添加了对透传链的支持。在版本 14.6 中,扩展为包括额外的传递类型的
file
、git
和url
。- 对覆盖规则的支持添加于 14.8 版本。
您可以通过在被扫描的仓库中定义规则集配置文件,来自定义我们的 SAST 分析器的行为。自定义有两种:
- 修改预定义规则的行为。包括:
- 合成覆盖,通过合成自定义配置替换预定义规则。仅适用于 nodejs-scan 和 semgrep。
禁用预定义规则
您可以禁用任何 SAST 分析器的预定义规则。
当您禁用规则时:
- 大多数分析器仍在扫描漏洞。结果在扫描完成后作为处理步骤被删除,并且它们不会出现在
gl-sast-report.json
产物中。 - 已禁用规则的漏洞发现不再出现在流水线安全选项卡中。
- 默认分支上禁用规则的现有漏洞发现在漏洞报告中标记为不再检测。
基于 Semgrep 的分析器以不同方式处理禁用的规则:
- 为了提高性能,基于 Semgrep 的分析器根本不扫描禁用的规则。
- 如果您在基于 Semgrep 的分析器中禁用规则,则在将
sast-ruleset.toml
文件合并到默认分支后,该规则的现有漏洞发现将自动解决。
覆盖预定义规则
可以为任何 SAST 分析器覆盖预定义规则的某些属性。这在使 SAST 适应您现有的工作流程或工具时非常有用。例如,您可能希望根据组织策略覆盖漏洞的严重性,或者选择不同的消息显示在漏洞报告中。
合成自定义配置
您可以完全替换某些 SAST 分析器的预定义规则:
- nodejs-scan - 您可以将默认的 njsscan 配置文件替换为您自己的。
- semgrep - 您可以用自己的规则集替换极狐GitLab 维护的规则集。
透传配置在运行时组成透传链,并进行评估后生成完整的配置,然后针对新配置执行底层扫描器。
有多种透传类型允许您以不同的方式提供配置,例如使用提交到您的仓库的文件,或在规则集配置文件中内联。您还可以选择如何处理链中的后续传递;他们可以覆盖或附加到以前的配置。
创建配置文件
创建规则集配置文件:
- 在项目的根目录下创建一个
.gitlab
目录(如果不存在的话)。 - 在
.gitlab
目录中创建一个名为sast-ruleset.toml
的文件。
Schema
顶层部分
顶层部分包含定义为 TOML 表的一个或多个配置。
设置 | 描述 |
---|---|
[$analyzer] |
声明分析器的配置部分。该名称遵循 SAST 分析器列表中定义的蛇形名称。 |
配置示例:
[semgrep]
...
避免创建修改现有规则和合成自定义规则集的配置部分,因为后者完全取代了预定义规则。
[$analyzer]
配置部分
[$analyzer]
部分允许您自定义分析器的行为。有效属性因您进行的配置类型而异。
设置 | 适用于 | 描述 |
---|---|---|
[[$analyzer.ruleset]] |
预定义规则 | 定义对现有规则的修改。 |
interpolate |
所有 | 如果设置为 true ,则可以在配置中使用 $VAR 来评估环境变量。请谨慎使用此功能,以免泄露 secret 或令牌。(默认值:false ) |
description |
透传 | 自定义规则集的描述。 |
targetdir |
透传 | 应保留最终配置的目录。如果为空,将创建一个具有随机名称的目录。该目录最多可包含 100MB 的文件。 |
validate |
透传 | 如果设置为 true ,则验证每个透传的内容。验证适用于 yaml 、xml 、json 和 toml 内容。正确的验证器是根据 [[$analyzer.passthrough]] 部分的 target 参数中使用的扩展来识别的。(默认值:false ) |
timeout |
透传 | 在超时之前评估透传链所花费的最长时间。超时不能超过 300 秒。(默认值:60) |
interpolate
下面的示例显示了使用 $GITURL
环境变量访问私有仓库的配置。该变量包含用户名和令牌(例如 https://user:token@url
),因此它们未明确存储在配置文件中。
[semgrep]
description = "My private Semgrep ruleset"
interpolate = true
[[semgrep.passthrough]]
type = "git"
value = "$GITURL"
ref = "refs/heads/main"
[[$analyzer.ruleset]]
部分
[[$analyzer.ruleset]]
部分针对并修改单个预定义规则。您可以为每个分析器定义一个或多个。
设置 | 描述 |
---|---|
disable |
是否应禁用规则。(默认值:false ) |
[$analyzer.ruleset.identifier] |
选择要修改的预定义规则。 |
[$analyzer.ruleset.override] |
定义规则的覆盖。 |
配置示例:
[semgrep]
[[semgrep.ruleset]]
disable = true
...
[$analyzer.ruleset.identifier]
部分
[$analyzer.ruleset.identifier]
部分定义了您希望修改的预定义规则的标识符。
设置 | 描述 |
---|---|
type |
预定义规则使用的标识符类型。 |
value |
预定义规则使用的标识符的值。 |
您可以通过查看分析器生成的 gl-sast-report.json
来查找 type
和 value
的正确值。
您可以从分析器的 CI 作业中下载此文件作为作业产物。
例如,下面的代码片段显示了来自具有三个标识符的 semgrep
规则的发现。JSON 对象中的 type
和 value
键对应于您应在该部分中提供的值。
...
"vulnerabilities": [
{
"id": "7331a4b7093875f6eb9f6eb1755b30cc792e9fb3a08c9ce673fb0d2207d7c9c9",
"category": "sast",
"message": "Key Exchange without Entity Authentication",
"description": "Audit the use of ssh.InsecureIgnoreHostKey\n",
...
"identifiers": [
{
"type": "semgrep_id",
"name": "gosec.G106-1",
"value": "gosec.G106-1"
},
{
"type": "cwe",
"name": "CWE-322",
"value": "322",
"url": "https://cwe.mitre.org/data/definitions/322.html"
},
{
"type": "gosec_rule_id",
"name": "Gosec Rule ID G106",
"value": "G106"
}
]
}
...
]
...
配置示例:
[semgrep]
[[semgrep.ruleset]]
[semgrep.ruleset.identifier]
type = "semgrep_id"
value = "gosec.G106-1
...
[$analyzer.ruleset.override]
部分
[$analyzer.ruleset.override]
部分允许您覆盖预定义规则的属性。
设置 | 描述 |
---|---|
description |
议题的详细描述。 |
message |
(已废弃)议题的详细描述。 |
name |
规则的名称。 |
severity |
规则的严重性。有效选项是:Critical 、High 、Medium 、Low 、Unknown 、Info
|
message
由分析器填写,但它已被弃用,取而代之的是 name
和 description
。配置示例:
[semgrep]
[[semgrep.ruleset]]
[semgrep.ruleset.override]
severity = "Critical"
name = "Command injection"
...
[[$analyzer.passthrough]]
部分
nodejs-scan
和 semgrep
分析器支持。[[$analyzer.passthrough]]
部分允许您为分析器合成自定义配置。每个分析器最多可以定义 20 个。透传传递被组合成一个透传链,该链评估为一个完整的配置,该配置替换了分析器的预定义规则。
透传按顺序评估。链中稍后列出的传递具有更高的优先级,并且可以覆盖或附加到先前传递产生的数据(取决于 mode
)。对于需要使用或修改现有配置的情况很有用。
单次透传生成的数据量限制为 1MB。
设置 | 适用于 | 描述 |
---|---|---|
type |
所有 |
file 、raw 、git 或 url 之一。 |
target |
所有 | 包含透传评估写入的数据的目标文件。如果为空,则使用随机文件名。 |
mode |
所有 | 如果 overwrite ,则覆盖 target 文件。如果使用 append ,新内容将附加到 target 文件。请注意,git 类型仅支持 overwrite 。(默认:overwrite ) |
ref |
type = "git" |
包含要提取的分支或 SHA 的名称。使用分支名称时,请以 refs/heads/<branch> 的形式指定,而不是 refs/remotes/<remote_name>/<branch> 。 |
subdir |
type = "git" |
用于选择 Git 仓库的一个子目录作为配置源。 |
value |
所有 | 对于 file 、url 和 git 类型,定义文件或 Git 仓库的位置。对于 raw 类型,包含内联配置。 |
validator |
所有 | 用于在评估透传后在目标文件上显式调用验证器(xml 、yaml 、json 、toml )。 |
透传类型
类型 | 描述 |
---|---|
file |
使用 Git 仓库中存在的文件。 |
raw |
提供内联配置。 |
git |
从远端 Git 仓库中拉取配置。 |
url |
使用 HTTP 获取配置。 |
raw
透传传递时,建议将 sast-ruleset.toml
文件中的所有缩进格式化为空格。YAML 规范要求制表符上有空格,除非相应地表示缩进,否则分析器将无法解析您的自定义规则集。示例
禁用 SAST 分析器的预定义规则
使用以下自定义规则集配置,报告中将省略以下规则:
-
semgrep
规则的semgrep_id
为gosec.G106-1
或cwe
为322
。 -
sobelow
规则带有sql_injection
的sobelow_rule_id
。 -
flawfinder
规则使用memcpy
的flawfinder_func_name
。
[semgrep]
[[semgrep.ruleset]]
disable = true
[semgrep.ruleset.identifier]
type = "semgrep_id"
value = "gosec.G106-1"
[[semgrep.ruleset]]
disable = true
[semgrep.ruleset.identifier]
type = "cwe"
value = "322"
[sobelow]
[[sobelow.ruleset]]
disable = true
[sobelow.ruleset.identifier]
type = "sobelow_rule_id"
value = "sql_injection"
[flawfinder]
[[flawfinder.ruleset]]
disable = true
[flawfinder.ruleset.identifier]
type = "flawfinder_func_name"
value = "memcpy"
覆盖 SAST 分析器的预定义规则
使用以下自定义规则集配置,使用类型为 CWE
且值为 322
的 semgrep
发现的漏洞的严重性将被覆盖为 Critical
。
[semgrep]
[[semgrep.ruleset]]
[semgrep.ruleset.identifier]
type = "CWE"
value = "322"
[semgrep.ruleset.override]
severity = "Critical"
使用 nodejs-scan
的原始透传合成自定义配置
使用以下自定义规则集配置,nodejs-scan
分析器的预定义行为将替换为自定义配置。
用于 value
的语法遵循 njsscan 配置格式。
[nodejs-scan]
description = "My custom ruleset for nodejs-scan"
[[nodejs-scan.passthrough]]
type = "raw"
value = '''
---
- nodejs-extensions:
- .js
template-extensions:
- .new
- .hbs
- ''
ignore-filenames:
- skip.js
ignore-paths:
- __MACOSX
- skip_dir
- node_modules
ignore-extensions:
- .hbs
ignore-rules:
- regex_injection_dos
- pug_jade_template
- express_xss
'''
使用 semgrep
的文件透传合成自定义配置
使用以下自定义规则集配置,semgrep
分析器的预定义规则集将替换为包含在被扫描仓库中名为 my-semgrep-rules.yaml
的文件中的自定义规则集。
# my-semgrep-rules.yml
---
rules:
- id: my-custom-rule
pattern: print("Hello World")
message: |
Unauthorized use of Hello World.
severity: ERROR
languages:
- python
[semgrep]
description = "My custom ruleset for Semgrep"
[[semgrep.passthrough]]
type = "file"
value = "my-semgrep-rules.yml"
使用 semgrep
的透传链合成自定义配置
使用以下自定义规则集配置,semgrep
分析器的预定义规则集将替换为通过评估四个透传链生成的自定义规则集。每次透传都会生成一个文件,该文件将写入容器内的 /sgrules
目录。设置了 60 秒的 timeout
,以防任何 Git 远端没有响应。
此示例中演示了不同的透传类型:
- 两次
git
透传,第一次从myrules
Git 仓库拉取refs/heads/test
,第二次从sast-rules
仓库拉取修订版97f7686
,并且只考虑go
子目录中的文件。-
sast-rules
条目具有更高的优先级,因为它出现在配置的后面。 - 如果两次检出之间存在文件名冲突,则来自
sast-rules
仓库的文件将覆盖来自myrules
仓库的文件。
-
- 一个
raw
透传,它将value
写入/sgrules/insecure.yml
。 - 一个
url
透传,它获取托管在 URL 上的配置并将其写入/sgrules/gosec.yml
。
之后,使用位于 /sgrules
下的最终配置调用 Semgrep。
[semgrep]
description = "My custom ruleset for Semgrep"
targetdir = "/sgrules"
timeout = 60
[[semgrep.passthrough]]
type = "git"
value = "https://gitlab.com/user/myrules.git"
ref = "refs/heads/test"
[[semgrep.passthrough]]
type = "git"
value = "https://gitlab.com/gitlab-org/secure/gsoc-sast-vulnerability-rules/playground/sast-rules.git"
ref = "97f7686db058e2141c0806a477c1e04835c4f395"
subdir = "go"
[[semgrep.passthrough]]
type = "raw"
target = "insecure.yml"
value = """
rules:
- id: "insecure"
patterns:
- pattern: "func insecure() {...}"
message: |
Insecure function insecure detected
metadata:
cwe: "CWE-200: Exposure of Sensitive Information to an Unauthorized Actor"
severity: "ERROR"
languages:
- "go"
"""
[[semgrep.passthrough]]
type = "url"
value = "https://semgrep.dev/c/p/gosec"
target = "gosec.yml"
配置链中透传模式
您可以选择如何处理链中透传之间发生的文件名冲突。默认覆盖同名的现有文件,但您可以选择 mode = append
来将后面文件的内容附加到前面的文件上。
您只能对 file
、url
和 raw
透传类型使用 append
模式。
通过以下自定义规则集配置,两个 raw
透传用于迭代组装 /sgrules/my-rules.yml
文件,然后将其作为规则集提供给 Semgrep。每个透传都会将一个规则附加到规则集中。根据 Semgrep 规则语法,第一个透传负责初始化顶层 rules
对象。
[semgrep]
description = "My custom ruleset for Semgrep"
targetdir = "/sgrules"
validate = true
[[semgrep.passthrough]]
type = "raw"
target = "my-rules.yml"
value = """
rules:
- id: "insecure"
patterns:
- pattern: "func insecure() {...}"
message: |
Insecure function 'insecure' detected
metadata:
cwe: "..."
severity: "ERROR"
languages:
- "go"
"""
[[semgrep.passthrough]]
type = "raw"
mode = "append"
target = "my-rules.yml"
value = """
- id: "secret"
patterns:
- pattern-either:
- pattern: '$MASK = "..."'
- metavariable-regex:
metavariable: "$MASK"
regex: "(password|pass|passwd|pwd|secret|token)"
message: |
Use of hard-coded password
metadata:
cwe: "..."
severity: "ERROR"
languages:
- "go"
"""
# /sgrules/my-rules.yml
rules:
- id: "insecure"
patterns:
- pattern: "func insecure() {...}"
message: |
Insecure function 'insecure' detected
metadata:
cwe: "..."
severity: "ERROR"
languages:
- "go"
- id: "secret"
patterns:
- pattern-either:
- pattern: '$MASK = "..."'
- metavariable-regex:
metavariable: "$MASK"
regex: "(password|pass|passwd|pwd|secret|token)"
message: |
Use of hard-coded password
metadata:
cwe: "..."
severity: "ERROR"
languages:
- "go"