Help us learn about your current experience with the documentation. Take the survey.

自定义规则集

  • Tier: Ultimate
  • Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated

您可以通过在被扫描的仓库中定义规则集配置文件来自定义我们的 SAST 分析器的行为。有两种自定义方式:

GitLab Advanced SAST 仅支持修改预定义规则的行为,不支持替换预定义规则。

禁用预定义规则

您可以禁用任何 SAST 分析器的预定义规则。

当您禁用一条规则时:

  • 所有支持自定义规则集的 SAST 分析器仍然会扫描该漏洞。扫描完成后,结果会被移除,不会出现在 gl-sast-report.json 工件 中。GitLab Advanced SAST 的不同之处在于,它会在初始扫描中排除已禁用的规则。
  • 已禁用规则的发现不再出现在流水线安全标签页中。
  • 默认分支上已禁用规则的现有发现会在漏洞报告中被标记为不再检测到

基于 Semgrep 的分析器处理已禁用规则的方式不同:

  • 如果您在基于 Semgrep 的分析器中禁用一条规则,当您将 sast-ruleset.toml 文件合并到默认分支后,该规则的现有漏洞发现会自动解决

有关如何配置此行为的信息,请参见模式示例部分。

覆盖预定义规则的元数据

您可以覆盖任何 SAST 分析器预定义规则的某些属性。这在将 SAST 适配到您现有的工作流程或工具时很有用。例如,您可能希望根据组织策略覆盖漏洞的严重性,或在漏洞报告中选择显示不同的消息。

有关如何配置此行为的信息,请参见模式示例部分。

构建自定义配置

您可以使用自己的规则替换基于 Semgrep 的分析器GitLab 维护的规则集

您通过直通提供自定义配置,这些直通在运行时被组合成一个直通链,并经过评估以生成完整配置。然后,底层扫描器会针对这个新配置执行。

有多种直通类型允许您以不同方式提供配置,例如使用提交到您仓库的文件或内联在规则集配置文件中。您还可以选择如何处理链中的后续直通;它们可以覆盖或附加到之前的配置。

有关如何配置此行为的信息,请参见模式示例部分。

创建配置文件

要创建规则集配置文件:

  1. 如果项目根目录下尚不存在,请创建一个 .gitlab 目录。
  2. .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"

有关高级用法,请参见指定私有远程配置示例

排查远程配置文件问题

如果远程配置文件似乎没有正确应用自定义,可能的原因有:

  1. 您的仓库有本地的 .gitlab/sast-ruleset.toml 文件。
  2. 身份验证存在问题。
    • 要检查这是否是问题的原因,请尝试引用不需要身份验证的仓库位置的配置文件。

模式

顶级部分

顶级部分包含一个或多个配置部分,定义为 TOML 表

设置 描述
[$analyzer] 声明分析器的配置部分。名称遵循 SAST 分析器列表中定义的名称。

配置示例:

[semgrep]
...

避免创建修改现有规则和构建自定义规则集的配置部分,因为后者会完全替换预定义规则。

[$analyzer] 配置部分

[$analyzer] 部分允许您自定义分析器的行为。有效属性根据您正在进行的配置类型而有所不同。

设置 适用于 描述
[[$analyzer.ruleset]] 预定义规则 定义对现有规则的修改。
interpolate 所有 如果设置为 true,您可以在配置中使用 $VAR 来评估环境变量。请谨慎使用此功能,以免泄露机密或令牌。(默认:false
description 直通 自定义规则的描述。
targetdir 直通 最终配置应持久化的目录。如果为空,将创建一个随机名称的目录。该目录最多可包含 100 MB 的文件。如果 SAST 作业以非 root 用户权限运行,请确保活动用户对此目录具有读写权限。
validate 直通 如果设置为 true,将验证每个直通的内容。验证适用于 yamlxmljsontoml 内容。根据 [[$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 来查找 typevalue 的正确值。您可以从分析器的 CI 作业中将此文件作为工件下载。

例如,下面的代码片段显示了来自 semgrep 规则的发现,该规则有三个标识符。JSON 对象中的 typevalue 键对应于您应该在此部分提供的值。

...
  "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 规则的严重性。有效选项为:CriticalHighMediumLowUnknownInfo

虽然 message 由分析器填充,但它已被弃用,转而使用 namedescription

配置示例:

[semgrep]
  [[semgrep.ruleset]]
    [semgrep.ruleset.override]
      severity = "Critical"
      name = "命令注入"
    ...

[[$analyzer.passthrough]] 部分

直通配置仅适用于基于 Semgrep 的分析器

[[$analyzer.passthrough]] 部分允许您为分析器构建自定义配置。每个分析器可以定义最多 20 个这样的部分。直通被组合成一个_直通链_,该链评估为完整的配置,替换分析器的预定义规则。

直通按顺序评估。链中列出的后续直通具有更高的优先级,可以覆盖或附加到先前直通提供的数据(取决于 mode)。这在您需要使用或修改现有配置的情况下很有用。

单个直通生成的配置大小限制为 10 MB。

设置 适用于 描述
type 所有 filerawgiturl 之一。
target 所有 包含直通评估写入数据的目标文件。如果为空,将使用随机文件名。
mode 所有 如果为 overwrite,则覆盖 target 文件。如果为 append,则将新内容附加到 target 文件。git 类型仅支持 overwrite。(默认:overwrite
ref type = "git" 包含要拉取的分支、标签或 SHA 的名称
subdir type = "git" 用于选择 Git 存储库的子目录作为配置源。
value 所有 对于 fileurlgit 类型,定义文件或 Git 存储库的位置。对于 raw 类型,包含内联配置。
validator 所有 用于在直通评估后显式调用验证器(xmlyamljsontoml)对目标文件进行验证。

直通类型

类型 描述
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_idgosec.G106-1cwe322 的规则。
  • sobelow 规则中 sobelow_rule_idsql_injection 的规则。
  • flawfinder 规则中 flawfinder_func_namememcpy 的规则。
[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 直通,第一个从 myrules Git 存储库拉取 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 来将后续文件的内容附加到较早文件上。

您只能对 fileurlraw 直通类型使用 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:$PERSONAL_ACCESS_TOKEN@gitlab.com/example-group/example-ruleset-project@c8ea7e3ff126987fb4819cc35f2310755511c2ab"

演示项目

演示项目说明了其中一些配置选项。

这些项目中的许多项目说明了使用远程规则集来覆盖或禁用规则,并按它们适用的分析器分组。

还有一些视频演示介绍了设置远程规则集: