自定义规则集
- Tier: Ultimate
- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
您可以通过在被扫描的仓库中定义规则集配置文件来自定义我们的 SAST 分析器的行为。有两种自定义方式:
- 修改预定义规则的行为。这包括:
- 禁用预定义规则。所有分析器都支持此功能。
- 覆盖预定义规则的元数据。所有分析器都支持此功能。
- 通过使用直通构建自定义配置来替换预定义规则。仅适用于基于 Semgrep 的分析器。
GitLab Advanced SAST 仅支持修改预定义规则的行为,不支持替换预定义规则。
禁用预定义规则
您可以禁用任何 SAST 分析器的预定义规则。
当您禁用一条规则时:
- 所有支持自定义规则集的 SAST 分析器仍然会扫描该漏洞。扫描完成后,结果会被移除,不会出现在
gl-sast-report.json工件 中。GitLab Advanced SAST 的不同之处在于,它会在初始扫描中排除已禁用的规则。 - 已禁用规则的发现不再出现在流水线安全标签页中。
- 默认分支上已禁用规则的现有发现会在漏洞报告中被标记为
不再检测到。
基于 Semgrep 的分析器处理已禁用规则的方式不同:
- 如果您在基于 Semgrep 的分析器中禁用一条规则,当您将
sast-ruleset.toml文件合并到默认分支后,该规则的现有漏洞发现会自动解决。
覆盖预定义规则的元数据
您可以覆盖任何 SAST 分析器预定义规则的某些属性。这在将 SAST 适配到您现有的工作流程或工具时很有用。例如,您可能希望根据组织策略覆盖漏洞的严重性,或在漏洞报告中选择显示不同的消息。
构建自定义配置
您可以使用自己的规则替换基于 Semgrep 的分析器的 GitLab 维护的规则集。
您通过直通提供自定义配置,这些直通在运行时被组合成一个直通链,并经过评估以生成完整配置。然后,底层扫描器会针对这个新配置执行。
有多种直通类型允许您以不同方式提供配置,例如使用提交到您仓库的文件或内联在规则集配置文件中。您还可以选择如何处理链中的后续直通;它们可以覆盖或附加到之前的配置。
创建配置文件
要创建规则集配置文件:
- 如果项目根目录下尚不存在,请创建一个
.gitlab目录。 - 在
.gitlab目录中创建一个名为sast-ruleset.toml的文件。
指定远程配置文件
您可以设置一个 CI/CD 变量来使用存储在当前仓库之外的规则集配置文件。这可以帮助您在多个项目中应用相同的规则。
SAST_RULESET_GIT_REFERENCE 变量使用类似于 Git URL 的格式来指定项目 URI、可选的身份验证和可选的 Git SHA。该变量使用以下格式:
[<AUTH_USER>[:<AUTH_PASSWORD>]@]<PROJECT_PATH>[@<GIT_SHA>]如果项目中有已提交的 .gitlab/sast-ruleset.toml 文件,则该本地配置优先,不会使用来自 SAST_RULESET_GIT_REFERENCE 的文件。
以下示例启用 SAST并使用共享的规则集自定义文件。在此示例中,文件位于 example-ruleset-project 的默认分支上的路径 .gitlab/sast-ruleset.toml。
include:
- template: Jobs/SAST.gitlab-ci.yml
variables:
SAST_RULESET_GIT_REFERENCE: "gitlab.com/example-group/example-ruleset-project"有关高级用法,请参见指定私有远程配置示例。
排查远程配置文件问题
如果远程配置文件似乎没有正确应用自定义,可能的原因有:
- 您的仓库有本地的
.gitlab/sast-ruleset.toml文件。- 默认情况下,如果存在本地文件,即使设置了远程配置变量也会使用本地文件。
- 您可以将 SECURE_ENABLE_LOCAL_CONFIGURATION CI/CD 变量 设置为
false以忽略本地配置文件。
- 身份验证存在问题。
- 要检查这是否是问题的原因,请尝试引用不需要身份验证的仓库位置的配置文件。
模式
顶级部分
顶级部分包含一个或多个配置部分,定义为 TOML 表。
| 设置 | 描述 |
|---|---|
[$analyzer] |
声明分析器的配置部分。名称遵循 SAST 分析器列表中定义的名称。 |
配置示例:
[semgrep]
...避免创建修改现有规则和构建自定义规则集的配置部分,因为后者会完全替换预定义规则。
[$analyzer] 配置部分
[$analyzer] 部分允许您自定义分析器的行为。有效属性根据您正在进行的配置类型而有所不同。
| 设置 | 适用于 | 描述 |
|---|---|---|
[[$analyzer.ruleset]] |
预定义规则 | 定义对现有规则的修改。 |
interpolate |
所有 | 如果设置为 true,您可以在配置中使用 $VAR 来评估环境变量。请谨慎使用此功能,以免泄露机密或令牌。(默认:false) |
description |
直通 | 自定义规则的描述。 |
targetdir |
直通 | 最终配置应持久化的目录。如果为空,将创建一个随机名称的目录。该目录最多可包含 100 MB 的文件。如果 SAST 作业以非 root 用户权限运行,请确保活动用户对此目录具有读写权限。 |
validate |
直通 | 如果设置为 true,将验证每个直通的内容。验证适用于 yaml、xml、json 和 toml 内容。根据 [[$analyzer.passthrough]] 部分中 target 参数使用的扩展名来识别适当的验证器。(默认:false) |
timeout |
直通 | 评估直通链的最长时间,超时后停止。超时时间不能超过 300 秒。(默认:60) |
interpolate
为降低泄露机密的风险,请谨慎使用此功能。
下面的示例显示了一个使用 $GITURL 环境变量访问私有仓库的配置。该变量包含用户名和令牌(例如 https://user:token@url),因此不会明确存储在配置文件中。
[semgrep]
description = "我的私有 Semgrep 规则集"
interpolate = true
[[semgrep.passthrough]]
type = "git"
value = "$GITURL"
ref = "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": "没有实体认证的密钥交换",
"description": "审计 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 = "命令注入"
...[[$analyzer.passthrough]] 部分
直通配置仅适用于基于 Semgrep 的分析器。
[[$analyzer.passthrough]] 部分允许您为分析器构建自定义配置。每个分析器可以定义最多 20 个这样的部分。直通被组合成一个_直通链_,该链评估为完整的配置,替换分析器的预定义规则。
直通按顺序评估。链中列出的后续直通具有更高的优先级,可以覆盖或附加到先前直通提供的数据(取决于 mode)。这在您需要使用或修改现有配置的情况下很有用。
单个直通生成的配置大小限制为 10 MB。
| 设置 | 适用于 | 描述 |
|---|---|---|
type |
所有 | file、raw、git 或 url 之一。 |
target |
所有 | 包含直通评估写入数据的目标文件。如果为空,将使用随机文件名。 |
mode |
所有 | 如果为 overwrite,则覆盖 target 文件。如果为 append,则将新内容附加到 target 文件。git 类型仅支持 overwrite。(默认:overwrite) |
ref |
type = "git" |
包含要拉取的分支、标签或 SHA 的名称 |
subdir |
type = "git" |
用于选择 Git 存储库的子目录作为配置源。 |
value |
所有 | 对于 file、url 和 git 类型,定义文件或 Git 存储库的位置。对于 raw 类型,包含内联配置。 |
validator |
所有 | 用于在直通评估后显式调用验证器(xml、yaml、json、toml)对目标文件进行验证。 |
直通类型
| 类型 | 描述 |
|---|---|
file |
使用 Git 存储库中存在的文件。 |
raw |
内联提供配置。 |
git |
从远程 Git 存储库拉取配置。 |
url |
使用 HTTP 获取配置。 |
当使用 raw 直通与 YAML 代码片段时,建议将 sast-ruleset.toml 文件中的所有缩进格式化为空格。YAML 规范要求使用空格而非制表符,除非缩进相应表示,否则分析器将无法解析您的自定义规则集。
示例
禁用预定义的 GitLab Advanced SAST 规则
您可以禁用 GitLab Advanced SAST 规则或编辑其元数据。以下示例基于不同条件禁用规则:
- CWE 标识符,标识整个漏洞类别。
- GitLab Advanced SAST 规则 ID,标识 GitLab Advanced SAST 中使用的特定检测策略。
- 关联的 Semgrep 规则 ID,包含在 GitLab Advanced SAST 发现中以实现兼容性。此附加元数据允许当两个分析器在同一位置创建相似发现时,发现能够自动转换。
这些标识符显示在每个漏洞的漏洞详细信息中。您还可以在可下载的 SAST 报告工件中看到每个标识符及其关联的 type。
[gitlab-advanced-sast]
[[gitlab-advanced-sast.ruleset]]
disable = true
[gitlab-advanced-sast.ruleset.identifier]
type = "cwe"
value = "89"
[[gitlab-advanced-sast.ruleset]]
disable = true
[gitlab-advanced-sast.ruleset.identifier]
type = "gitlab-advanced-sast_id"
value = "java-spring-csrf-unrestricted-requestmapping-atomic"
[[gitlab-advanced-sast.ruleset]]
disable = true
[gitlab-advanced-sast.ruleset.identifier]
type = "semgrep_id"
value = "java_cookie_rule-CookieHTTPOnly"禁用其他 SAST 分析器的预定义规则
使用以下自定义规则集配置,报告中将省略以下规则:
semgrep规则中semgrep_id为gosec.G106-1或cwe为322的规则。sobelow规则中sobelow_rule_id为sql_injection的规则。flawfinder规则中flawfinder_func_name为memcpy的规则。
[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"覆盖预定义规则元数据
使用以下自定义规则集配置,使用 semgrep 发现的类型为 CWE 且值为 322 的漏洞,其严重性被覆盖为 Critical。
[semgrep]
[[semgrep.ruleset]]
[semgrep.ruleset.identifier]
type = "cwe"
value = "322"
[semgrep.ruleset.override]
severity = "Critical"使用文件直通为 semgrep 构建自定义配置
使用以下自定义规则集配置,semgrep 分析器的预定义规则集被替换为存储在被扫描仓库中名为 my-semgrep-rules.yaml 的文件中的自定义规则集。
# my-semgrep-rules.yml
---
rules:
- id: my-custom-rule
pattern: print("Hello World")
message: |
未经授权使用 Hello World。
severity: ERROR
languages:
- python[semgrep]
description = "我的 Semgrep 自定义规则集"
[[semgrep.passthrough]]
type = "file"
value = "my-semgrep-rules.yml"使用直通链为 semgrep 构建自定义配置
使用以下自定义规则集配置,semgrep 分析器的预定义规则集被通过评估四个直通链生成的自定义规则集替换。每个直通生成一个文件,该文件被写入容器内的 /sgrules 目录。设置了 60 秒的 timeout,以防任何 Git 远程无响应。
此示例演示了不同的直通类型:
- 两个
git直通,第一个从myrulesGit 存储库拉取develop分支,第二个从sast-rules存储库拉取修订版97f7686,并仅考虑go子目录中的文件。sast-rules条目具有更高的优先级,因为它在配置中出现在后面。- 如果两个检出之间存在文件名冲突,
sast-rules存储库中的文件将覆盖myrules存储库中的文件。
- 一个
raw直通,将其value写入/sgrules/insecure.yml。 - 一个
url直通,获取托管在 URL 的配置并将其写入/sgrules/gosec.yml。
之后,Semgrep 使用位于 /sgrules 下的最终配置调用。
[semgrep]
description = "我的 Semgrep 自定义规则集"
targetdir = "/sgrules"
timeout = 60
[[semgrep.passthrough]]
type = "git"
value = "https://gitlab.com/user/myrules.git"
ref = "develop"
[[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
metadata:
cwe: "CWE-200: 向未经授权的参与者暴露敏感信息"
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 = "我的 Semgrep 自定义规则集"
targetdir = "/sgrules"
validate = true
[[semgrep.passthrough]]
type = "raw"
target = "my-rules.yml"
value = """
rules:
- id: "insecure"
patterns:
- pattern: "func insecure() {...}"
message: |
检测到不安全的函数 'insecure'
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: |
使用硬编码密码
metadata:
cwe: "..."
severity: "ERROR"
languages:
- "go"
"""# /sgrules/my-rules.yml
rules:
- id: "insecure"
patterns:
- pattern: "func insecure() {...}"
message: |
检测到不安全的函数 'insecure'
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: |
使用硬编码密码
metadata:
cwe: "..."
severity: "ERROR"
languages:
- "go"指定私有远程配置
以下示例启用 SAST并使用共享的规则集自定义文件。该文件:
- 使用安全存储在 CI 变量中的组访问令牌从需要身份验证的私有项目下载。
- 在特定的 Git 提交 SHA 而不是默认分支检出。
有关如何查找与组令牌关联的用户名,请参见组访问令牌。
include:
- template: Jobs/SAST.gitlab-ci.yml
variables:
SAST_RULESET_GIT_REFERENCE: "group_2504721_bot_7c9311ffb83f2850e794d478ccee36f5:[email protected]/example-group/example-ruleset-project@c8ea7e3ff126987fb4819cc35f2310755511c2ab"演示项目
有演示项目说明了其中一些配置选项。
这些项目中的许多项目说明了使用远程规则集来覆盖或禁用规则,并按它们适用的分析器分组。
还有一些视频演示介绍了设置远程规则集: