{{< details >}}

  • Tier: 旗舰版
  • Offering: JihuLab.com, 私有化部署

{{< /details >}}

{{< history >}}

  • 在极狐GitLab 16.2 中,支持指定不明确的 passthrough 引用

{{< /history >}}

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

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

禁用预定义规则

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

当您禁用规则时:

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

  • 为了提高性能,基于 Semgrep 的分析器根本不扫描禁用规则。
  • 如果您在基于 Semgrep 的分析器中禁用规则,当您将 sast-ruleset.toml 文件合并到默认分支后,该规则的现有漏洞发现会自动解决

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

覆盖预定义规则的元数据

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

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

构建自定义配置

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

您通过 passthroughs 提供您的自定义,这些 passthroughs 在运行时被组成一个 passthrough 链并评估以生成完整的配置。然后根据这个新配置执行基础扫描仪。

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

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

创建配置文件

要创建规则集配置文件:

  1. 在项目的根目录创建一个 .gitlab 目录,如果不存在的话。
  2. .gitlab 目录中创建一个名为 sast-ruleset.toml 的文件。

指定远程配置文件

{{< history >}}

  • 引入于极狐GitLab 16.1。

{{< /history >}}

您可以设置一个CI/CD 变量来使用存储在当前存储库之外的规则集配置文件。这可以帮助您在多个项目中应用相同的规则。

SAST_RULESET_GIT_REFERENCE 变量使用与Git URLs类似的格式来指定项目 URI、可选认证和可选 Git SHA。该变量使用以下格式:

[<AUTH_USER>[:<AUTH_PASSWORD>]@]<PROJECT_PATH>[@<GIT_SHA>]

{{< alert type=”note” >}}

如果项目有一个 .gitlab/sast-ruleset.toml 文件被提交,那么该本地配置优先,并且不使用 SAST_RULESET_GIT_REFERENCE 中的文件。

{{< /alert >}}

以下示例启用 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 Passthroughs 自定义规则集的描述。
targetdir Passthroughs 最终配置应持久化的目录。如果为空,则创建一个随机名称的目录。目录最多可包含 100 MB 的文件。如果 SAST 作业以非 root 用户权限运行,请确保活动用户对该目录具有读取和写入权限。
validate Passthroughs 如果设置为 true,则验证每个 passthrough 的内容。验证适用于 yamlxmljsontoml 内容。根据 [[$analyzer.passthrough]] 部分中的 target 参数使用的扩展名识别正确的验证器。(默认值:false
timeout Passthroughs 在超时之前评估 passthrough 链的最大时间。超时不能超过 300 秒。(默认值:60)

interpolate

{{< alert type=”warning” >}}

为了减少泄露密钥的风险,请谨慎使用此功能。

{{< /alert >}}

下面的示例显示了使用 $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": "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

{{< alert type=”note” >}}

虽然 message 由分析器填充,但它已被弃用,取而代之的是 namedescription

{{< /alert >}}

配置示例:

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

[[$analyzer.passthrough]] 部分

{{< alert type=”note” >}}

Passthrough 配置仅适用于基于 Semgrep 的分析器。

{{< /alert >}}

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

Passthroughs 按顺序评估。在链中稍后的 passthroughs 具有更高的优先级,并且可以覆盖或附加到之前 passthroughs 生成的数据(取决于 mode)。这对于需要使用或修改现有配置的情况很有用。

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

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

Passthrough 类型

类型 描述
file 使用 Git 存储库中存在的文件。
raw 内联提供配置。
git 从远程 Git 存储库拉取配置。
url 使用 HTTP 获取配置。

{{< alert type=”warning” >}}

当使用带有 YAML 片段的 raw passthrough 时,建议将 sast-ruleset.toml 文件中的所有缩进格式化为空格。YAML 规范要求使用空格而不是制表符,除非缩进以相应的方式表示,否则分析器无法解析您的自定义规则集。

{{< /alert >}}

示例

禁用预定义的极狐GitLab 高级 SAST 规则

您可以禁用极狐GitLab 高级 SAST 规则或编辑其元数据。以下示例根据不同的标准禁用规则:

  • CWE 标识符,它标识整个漏洞类别。
  • 极狐GitLab 高级 SAST 规则 ID,它标识在极狐GitLab 高级 SAST 中使用的特定检测策略。
  • 关联的 Semgrep 规则 ID,它包含在极狐GitLab 高级 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"

使用文件 passthrough 为 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 = "我的 Semgrep 自定义规则集"

  [[semgrep.passthrough]]
    type  = "file"
    value = "my-semgrep-rules.yml"

使用 passthrough 链为 semgrep 构建自定义配置

通过以下自定义规则集配置,semgrep 分析器的预定义规则集被评估为四个 passthrough 组成的链生成的自定义规则集替换。每个 passthrough 生成一个文件,写入到容器内的 /sgrules 目录中。设置了 60 秒的 timeout 以防任何 Git 远程无响应。

这个示例中展示了不同的 passthrough 类型:

  • 两个 git passthrough,第一个从 myrules Git 存储库拉取 develop 分支,第二个从 sast-rules 存储库拉取修订版 97f7686,并仅考虑 go 子目录中的文件。
    • 由于出现在配置中较晚,sast-rules 条目具有更高的优先级。
    • 如果两个检出之间存在文件名冲突,则 sast-rules 存储库中的文件会覆盖 myrules 存储库中的文件。
  • 一个 raw passthrough,它将其 value 写入到 /sgrules/insecure.yml
  • 一个 url passthrough,它获取一个托管在 URL 上的配置并将其写入到 /sgrules/gosec.yml

之后,使用位于 /sgrules 下的最终配置调用 Semgrep。

[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 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"

配置 passthrough 链中的模式

您可以选择如何处理 passthrough 链中发生的文件名冲突。默认行为是覆盖具有相同名称的现有文件,但您可以选择 mode = append 来将后续文件的内容附加到之前的文件上。

您可以仅对 fileurlraw passthrough 类型使用 append 模式。

通过以下自定义规则集配置,两个 raw passthrough 用于迭代地组装 /sgrules/my-rules.yml 文件,然后将其作为规则集提供给 Semgrep。每个 passthrough 将单个规则附加到规则集。第一个 passthrough 负责根据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 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"

指定私有远程配置

以下示例启用 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"