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

安全部分分析器开发

分析器以Docker镜像的形式发布,在CI管道环境中执行。本指南介绍了跨分析器的开发和测试实践。

共享模块

分析器之间共享了许多用于通用行为和接口的Go模块:

  • command Go包实现了CLI接口。
  • common 项目提供了用于日志记录、证书处理和目录搜索功能的杂项共享模块。
  • report Go包的ReportFinding结构体序列化JSON报告。
  • template 项目为新分析器提供脚手架。

如何使用分析器

分析器以Docker镜像的形式发布。例如,要运行Semgrep Docker镜像扫描工作目录:

  1. 进入要扫描的源代码目录。

  2. 运行docker login registry.gitlab.com并提供用户名以及具有至少read_registry权限的个人访问令牌项目访问令牌

  3. 运行Docker镜像:

    docker run \
        --interactive --tty --rm \
        --volume "$PWD":/tmp/app \
        --env CI_PROJECT_DIR=/tmp/app \
        -w /tmp/app \
        registry.gitlab.com/gitlab-org/security-products/analyzers/semgrep:latest /analyzer run
  4. Docker容器会在挂载的项目目录中生成一份报告,报告文件名对应分析器类别。例如,SAST会生成一个名为gl-sast-report.json的文件。

分析器开发

要更新分析器:

  1. 修改Go源代码。
  2. 构建新的Docker镜像。
  3. 针对测试项目运行分析器。
  4. 比较生成的报告与预期结果。

以下是创建名为analyzer的Docker镜像的方法:

docker build -t analyzer .

例如,要测试Secret Detection,运行以下命令:

wget https://gitlab.com/gitlab-org/security-products/ci-templates/-/raw/master/scripts/compare_reports.sh
sh ./compare_reports.sh sd test/fixtures/gl-secret-detection-report.json test/expect/gl-secret-detection-report.json \
| patch -Np1 test/expect/gl-secret-detection-report.json && Git commit -m 'Update expectation' test/expect/gl-secret-detection-report.json
rm compare_reports.sh

你也可以为自己的环境编译二进制文件并在本地运行,但由于分析器的运行时依赖缺失,analyzerun可能无法正常工作。

以下是基于SpotBugs的示例:

go build -o analyzer
./analyzer search test/fixtures
./analyzer convert test/fixtures/app/spotbugsXml.Xml > ./gl-sast-report.json

安全阶段 CI/CD 模板和组件

安全阶段负责维护以下 CI/CD 模板和组件:

对您组的 CI/CD 模板和组件所做的更改必须始终同步,并且您还必须确定这些更改是否需要应用到最新的 CI/CD 模板上。

分析器也在用于离线环境的 Secure-Binaries.gitlab-ci.yml 文件中被引用。进行更改时,请确保此文件也保持同步。

执行条件

启用SAST 需要在 GitLab CI/CD 配置中包含一个预定义的 模板

以下独立标准决定了哪个分析器需要在项目中运行:

  1. SAST 模板使用 rules:exists 来确定基于某些文件的存在性来运行哪个分析器。例如,Brakeman 分析器 在存在 .rb 文件和 Gemfile 时运行。
  2. 每个分析器在实际分析之前会运行可定制的 匹配接口。例如:Flawfinder 检查 C/C++ 文件
  3. 对于一些运行在通用文件扩展名上的分析器,有一个基于 CI/CD 变量的检查。例如:Kubernetes 清单是用 YAML 编写的,所以 Kubesec 仅在设置了 SCAN_KUBERNETES_MANIFESTS 为 true 时运行。

第 1 步有助于防止计算配额的浪费,这些配额会被用于运行不适合项目的分析器。然而,由于 技术限制,它不能用于大型项目。因此,第 2 步作为最终检查,确保不匹配的分析器能够提前退出。

如何测试分析器

视频演示了依赖扫描分析器如何使用 下游管道 功能通过测试项目来测试分析器:

Sec 如何利用 GitLab 的下游管道功能端到端测试分析器

测试本地更改

若要测试共享模块(如 commandreport)的本地更改,你可以使用 go mod replace 指令来加载带有你本地更改的 command,而不是使用已远程标记版本的 command。例如:

go mod edit -replace gitlab.com/gitlab-org/security-products/analyzers/command/v3=/local/path/to/command

或者,你也可以通过手动更新 go.mod 文件达到相同效果:

module gitlab.com/gitlab-org/security-products/analyzers/awesome-analyzer/v2

replace gitlab.com/gitlab-org/security-products/analyzers/command/v3 => /path/to/command

require (
    ...
    gitlab.com/gitlab-org/security-products/analyzers/command/v3 v2.19.0
)

在 Docker 中测试本地更改

要在 go.mod 文件中使用 replace 与 Docker 配合:

  1. command 的内容复制到分析器的目录中。cp -r /path/to/command path/to/analyzer/command
  2. 在分析器的 Dockerfile 中添加一条复制语句:COPY command /command
  3. 更新 replace 语句以确保它与上述步骤中 COPY 语句的目标位置匹配: replace gitlab.com/gitlab-org/security-products/analyzers/command/v3 => /command

测试容器编排兼容性

用户可能使用除Docker以外的工具来编排其容器并运行分析器,例如containerdPodmanskopeo。为确保与这些工具的兼容性,我们通过计划管道定期测试所有分析器。如果测试失败,会触发Slack警报。

为避免在构建分析器Docker镜像时出现兼容性问题,请使用OCI媒体类型,而不是默认的专有Docker媒体类型。

除定期测试外,我们还确保ci-templates仓库用户的兼容性:

  1. 使用ci-templates docker-test.yml模板的分析器包含tests,以确保我们的Docker镜像在与支持的Docker工具配合下正常运行。

    这些测试在Merge Request管道和计划管道中执行,若镜像破坏了支持的Docker工具,则会阻止镜像发布。

  2. ci-templates docker.yml模板在构建分析器镜像时,为docker buildx命令指定了oci-mediatypes=true。这会使用OCI媒体类型而非Docker专有媒体类型来构建镜像。

创建新分析器或更改现有分析器镜像的位置时,将其添加到定期测试中,或考虑使用包含自动化测试的共享ci-templates

分析器脚本

analyzer-scripts仓库包含可用于与大多数分析器交互的脚本。它们使您能够在类似GitLab CI的环境中构建、运行和调试分析器,尤其适用于本地验证对分析器的更改。

有关更多信息,请参阅项目README

版本控制和发布流程

GitLab 安全产品采用与 GitLab MAJOR.MINOR 独立的版本控制系统。所有产品均遵循 语义化版本 的变体,并以 Docker 镜像形式提供。

Major 在 GitLab 每次重大版本发布时递增(当 允许破坏性变更 时)。Minor 用于新功能,Patch 则用于 bug 修复。

分析器以 Docker 镜像的形式发布,遵循以下规则:

  • 推送到默认分支的每次提交都会覆盖 edge 镜像标签
  • 推送到任意 awesome-feature 分支会生成对应的 awesome-feature 镜像标签
  • 每个 Git 标签会生成对应的 Major.Minor.Patch 镜像标签。手动任务可重写对应的 Majorlatest 镜像标签,使其指向此 Major.Minor.Patch

在大多数情况下,优先依赖 MAJOR 镜像,该镜像会自动更新至我们工具的最新建议或补丁。我们的 内置 CI 模板 固定到主要版本,但如果需要,用户可以直接覆盖其版本。

若要发布新的分析器 Docker 镜像,有两种不同的方式:

下图描述了发布新分析器版本时生成的 Docker 标签:

graph LR

A1[git tag v1.1.0]--> B1(run CI pipeline)
B1 -->|build and tag patch| D1[1.1.0]
B1 -->|tag minor| E1[1.1]
B1 -->|retag major| F1[1]
B1 -->|retag latest| G1[latest]

A2[git tag v1.1.1]--> B2(run CI pipeline)
B2 -->|build and tag patch| D2[1.1.1]
B2 -->|tag minor| E2[1.1]
B2 -->|retag major| F2[1]
B2 -->|retag latest| G2[latest]

A3[push to default branch]--> B3(run CI pipeline)
B3 -->|build and tag edge| D3[edge]

根据我们的持续部署流程,对于在 GitLab Rails 应用程序中没有对应组件的新组件,可以在任何时候发布。在组件与现有应用集成之前,不应因 我们的标准发布周期和流程 而阻塞迭代。

手动发布流程

  1. 确保 CHANGELOG.md 中新分析器的条目正确。
  2. 确保发布源(通常是 mastermain 分支)有通过流水线。
  3. 通过项目窗口左侧的 Deployments 菜单选择分析器项目的 Releases 子菜单来创建新发布。
  4. 选择 New release 打开 New Release 页面。
    1. Tag name 下拉框中,输入与 CHANGELOG.md 中相同的版本,例如 v2.4.2,并选择创建标签的选项(此处为 Create tag v2.4.2)。
    2. Release title 文本框中输入上述相同版本,例如 v2.4.2
    3. Release notes 文本框中,复制粘贴 CHANGELOG.md 中对应版本的说明。
    4. 其他设置保持默认值。
    5. 选择 Create release

完成上述流程并创建新发布后,将使用上述提供的 Tag name 创建新的 Git 标签。这会触发带有给定标签版本的新流水线,并构建新的分析器 Docker 镜像。

如果分析器使用了 analyzer.yml 模板,则上述 New release 流程触发的流水线会自动标记并部署新版本的分析器 Docker 镜像。

如果分析器未使用 analyzer.yml 模板,则需要手动标记并部署新版本的分析器 Docker 镜像:

  1. 通过项目窗口左侧的 CI/CD 菜单选择 Pipelines 子菜单。
  2. 当前应有一个正在运行的新流水线,使用之前相同的标签,例如 v2.4.2
  3. 流水线完成后,将处于 blocked 状态。
  4. 选择窗口右侧的 Manual job 播放按钮,并选择 tag version 以标记并部署新版本的分析器 Docker 镜像。

请根据你的最佳判断决定何时创建 Git 标签,这将触发发布作业。如果你无法决定,请征求他人的意见。

自动发布流程

在使用自动发布流程之前,必须执行以下操作:

  1. CREATE_GIT_TAG: true 配置为 CI/CD 环境变量。\n1. 检查 CI/CD 项目设置中的 Variables:\n \n - 如果项目位于 gitlab-org/security-products/analyzers 命名空间下,则会自动继承 GITLAB_TOKEN 环境变量,无需其他操作。\n - 如果项目不位于 gitlab-org/security-products/analyzers 命名空间下,则需要创建一个新的已屏蔽和隐藏的 GITLAB_TOKEN CI/CD 环境变量,并将其值设置为下面自动发布过程中使用的服务账户部分中描述的 @gl-service-dev-secure-analyzers-automation 账户的个人访问令牌。\n\n完成上述步骤后,自动发布流程按如下方式执行:\n\n1. 项目维护者将合并请求(MR)合并到默认分支。\n1. 触发默认流水线,并执行 upsert git tag 任务:\n - 如果 CHANGELOG.md 中的最新版本与某个 Git 标签匹配,则该任务无操作。\n - 否则,此任务会使用 releases API 自动创建新版本和 Git 标签。版本号和消息从项目 CHANGELOG.md 文件中的最新条目获取。\n1. 为新的 Git 标签自动触发流水线。此流水线发布分析器的 latestmajorminorpatch Docker 镜像。

自动发布过程中使用的服务账户

| 键 | 值 |\n|—————-|————————————————————————————————————————————|\n| 账户名称 | @gl-service-dev-secure-analyzers-automation |\n| 用途 | 用于创建版本/标签 |\n| 所属组 | gitlab-org/security-products |\n| 最大角色 | Developer |\n| 关联 GITLAB_TOKEN 的范围 | api |\n| GITLAB_TOKEN 的到期日期 | 2025年12月3日 |

服务账户的令牌轮换

@gl-service-dev-secure-analyzers-automation 服务账户的 GITLAB_TOKEN 必须 在上述[服务账户用于自动发布过程]中列出的 Expiry Date 之前通过以下步骤轮换:

  1. gl-service-dev-secure-analyzers-automation 用户身份登录。

    该账户的管理员列表可在服务账户访问请求 中找到。

    管理员可在共享的 GitLab 1password 保险箱中找到登录凭证。

  2. gl-service-dev-secure-analyzers-automation 服务账户创建一个新的个人访问令牌,范围为 api

  3. 将共享 GitLab 1password 保险箱中 GitLab API Token - gl-service-dev-secure-analyzers-automation 账户的 password 字段更新为步骤 2 中创建的新个人访问令牌,并将 Expires at 字段设置为令牌到期时间。

  4. 更新服务账户用于自动发布过程 表格中 GITLAB_TOKEN 字段的到期日期。

  5. 将以下变量设置为步骤 2 中创建的新个人访问令牌:

    对以下变量进行屏蔽和隐藏 至关重要。

    1. gitlab-org/security-products/analyzers 组的 GITLAB_TOKEN CI/CD 变量(链接)。

      这使得 gitlab-org/security-products/analyzers 命名空间下的所有项目都能继承此 GITLAB_TOKEN 值。

    2. gitlab-org/security-products/ci-templates 项目的 GITLAB_TOKEN CI/CD 变量(链接)。

      此处必须显式配置,因为 ci-templates 项目未嵌套在 gitlab-org/security-products/analyzers 命名空间下,因此不会继承 GITLAB_TOKEN 值。

      ci-templates 项目需要 GITLAB_TOKEN 来允许某些脚本执行 API 调用。待允许 JOB-TOKEN 访问 CI/lint 端点 完成后,此步骤可移除。

    3. gitlab-org/secure/tools/security-triage-automation 项目的 GITLAB_TOKEN CI/CD 变量(链接)。

      此处必须显式配置,因为 security-triage-automation 项目未嵌套在 gitlab-org/security-products/analyzers 命名空间下,因此不会继承 GITLAB_TOKEN 值。

    4. gitlab-advanced-sast 项目的 SEC_REGISTRY_PASSWORD CI/CD 变量(链接)。

      这使得我们的标签脚本 能从开发项目 registry.gitlab.com/gitlab-org/security-products/analyzers/<analyzer-name>/tmp 的私有容器注册表中拉取,并推送到公开可访问的容器注册表 registry.gitlab.com/security-products/<analyzer-name>

发布分析器后的步骤

  1. 分析器的 Docker 镜像新版本标记并部署后,使用对应的测试项目进行测试。

  2. 在相关组 Slack 频道宣布发布。示例如下:

    提醒:我刚刚发布了 ANALYZER_NAME ANALYZER_VERSIONLINK_TO_RELEASE

切勿删除已推送的 Git 标签,因为这些标签很可能被 Go 包注册表使用或缓存。

回溯关键修复或补丁

要将关键修复或补丁回溯到早期版本,请按照以下步骤操作。

  1. 如果不存在,从你要回溯修复的目标标签创建一个新分支。
    • 例如,如果最新稳定标签是 v4,而你正在将修复回溯到 v3,则创建一个名为 v3 的新分支。
  2. 提交一个针对你刚创建的分支的合并请求。
  3. 批准后,将该合并请求合并到该分支。
  4. 为该分支创建一个新标签。
  5. 如果分析器启用了自动发布流程,则会发布一个新版本。
  6. 如果没有,你必须遵循手动发布流程来发布新版本。
  7. 注意:发布流水线会覆盖最新的 edge 标签,因此最近的发布流水线的 tag edge 作业可能需要重新运行,以避免该标签的回归。

为大版本发布准备分析器

此过程适用于以下组:

其他组负责记录自己的大版本发布流程。

根据大版本发布是否包含破坏性变更,选择以下一种情况:

  1. 无破坏性变更的大版本发布
  2. 包含破坏性变更的大版本发布

无破坏性变更的大版本发布

假设当前分析器版本为 v{N}

  1. 配置受保护的标签和分支
  2. 在大版本的里程碑期间,当没有更多更改需要合并到 default 分支时:
    1. default 分支创建一个 v{N} 分支。

    2. default 分支中创建并合并一个新的合并请求,其中仅包含对 CHANGELOG.md 文件的以下更改:

      ## v{N+1}.0.0
      - 主要版本发布 (!<MR-ID>)
    3. 配置计划流水线

    4. 在CI/CD模板和组件中提升主要分析器版本

包含破坏性变更的大版本发布

假设当前分析器版本为 v{N}

  1. 配置受保护的标签和分支

  2. 创建一个新分支 v{N+1} 来“暂存”破坏性变更。

  3. 在大版本里程碑之前的各个里程碑中:

    • 将非破坏性变更合并到 default 分支(即 mastermain

    • 将破坏性变更合并到 v{N+1} 分支,并为每个变更在 CHANGELOG.md 文件中创建一个单独的 release candidate 条目:

      ## v{N+1}.0.0-rc.0
      - 某些破坏性变更 (!123)

      使用 发布候选版 允许我们在一次主要版本更新中发布所有破坏性变更,这符合语义化版本指南的要求,即仅在主要版本更新中进行破坏性变更。

  4. 在大版本的里程碑期间,当没有更多更改需要合并到 defaultv{N+1} 分支时:

    1. default 分支创建一个 v{N} 分支。

    2. v{N+1} 分支中创建一个合并请求,将所有 发布候选版 的变更日志条目整合为一个 v{N+1} 的单一条目。

      例如,如果 CHANGELOG.md 中包含以下 3 个 v{N+1} 版本的 发布候选版 条目:

      ## v{N+1}.0.0-rc.2
      - 又一个破坏性变更 (!125)
      
      ## v{N+1}.0.0-rc.1
      - 另一个破坏性变更 (!124)
      
      ## v{N+1}.0.0-rc.0
      - 某些破坏性变更 (!123)

      那么新的合并请求应更新 CHANGELOG.md,使其具有 v{N+1} 的单个主要版本,通过将所有 发布候选版 条目整合为一个条目:

      ## v{N+1}.0.0
      - 又一个破坏性变更 (!125)
      - 另一个破坏性变更 (!124)
      - 某些破坏性变更 (!123)
    3. 创建一个合并请求,将 v{N+1} 分支中的所有破坏性变更合并到 default 分支。

    4. 删除 v{N+1} 分支,因为它不再需要,因为 default 分支现在包含了 v{N+1} 分支的所有变更。

    5. 配置计划流水线

    6. 在CI/CD模板和组件中提升主要分析器版本

配置受保护标签和分支
  1. 确保 通配符 v* 被设置为项目的 受保护标签受保护分支

  2. 验证 gl-service-dev-secure-analyzers-automation 服务账户是否有权创建受保护标签。

    有关更多详情,请参阅 官方支持的镜像 部分的第 3.1 步。

配置计划流水线
  1. 确保存在三个计划流水线(必要时创建),并为所有流水线设置 PUBLISH_IMAGES: true
    • Republish images v{N}(针对 v{N} 分支)

      此计划流水线需要被创建

    • Daily build(针对 default 分支)

      此计划流水线应已存在

    • Republish images v{N-1}(针对 v{N-1} 分支)

      此计划流水线应已存在

  2. 删除 v{N-2} 分支的计划流水线(如果存在),因为我们仅支持 两个之前的版本
提升CI/CD模板和组件中的主要分析器版本

当所有 v{N+1} 分析器的镜像在 registry.gitlab.com/security-products/<ANALYZER-NAME>:<TAG> 下可用时,为属于您组的 安全阶段CI/CD模板和组件 中每个分析器创建新的合并请求以提升主要版本。

新分析器的开发

我们偶尔需要构建新的分析器项目以支持新的框架和工具。在此过程中,我们应遵循 我们的工程开源指南,包括许可和 代码标准

此外,若要编写能集成到GitLab应用的自定义分析器,需具备以下最小功能集:

检查清单

验证底层工具是否具有:

  • 宽松软件许可证
  • 无头执行(命令行工具)。
  • 可捆绑依赖项,以便打包为Docker镜像,通过GitLab Runner的 Linux或Windows Docker执行器 执行。
  • 基于文件名或扩展名可检测的兼容项目。
  • 离线执行(无需互联网访问)或可配置为使用自定义代理和/或CA证书。
  • 镜像与其他容器编排工具兼容(参见 测试容器编排兼容性)。

Dockerfile

Dockerfile 应使用名为 GitLab 的非特权用户。这是为了与Red Hat OpenShift实例兼容,后者不允许容器以管理员(root)用户运行。以非特权用户运行容器时需注意某些限制,例如需要在Docker文件系统上写入的任何文件均需为 GitLab 用户分配适当权限。有关更多详情,请参阅以下合并请求: 在Docker镜像中使用GitLab用户而非root

最小漏洞数据

有关所需字段的完整列表,请参阅 我们的安全报告模式

security-report-schema 仓库包含JSON模式,列出了每种报告类型所需的字段:

报告架构的兼容性

上传到 GitLab 作为制品的安全报告会在被摄取前进行验证

安全报告架构通过 SchemaVer 进行版本控制:MODEL-REVISION-ADDITION。Sec 部门负责管理 security-report-schemas 项目,包括 GitLab 与架构版本的兼容性。架构变更必须遵循产品范围的弃用指南

当引入新的 MODEL 版本时,采用新架构的分析器需确保未包含此新架构版本的 GitLab 部署仍能无错误或警告地摄取安全报告。

可通过以下方式实现:

  1. 在分析器中实现多架构版本支持。基于 GitLab 版本,分析器使用 GitLab 支持的最新架构版本来生成安全报告。
    • 优点:分析器可在运行时决定最优版本。
    • 缺点:实现工作量增加且复杂度提高。
  2. 发布新的分析器主要版本。未包含最新 MODEL 架构版本的实例继续使用生成 MODEL-1 版本报告的分析器版本。
    • 优点:保持分析器代码简洁。
    • 缺点:需维护额外的分析器版本。
  3. 延迟使用新架构。这依赖于 additionalProperties=true,允许报告中包含架构中不存在的属性。通常节奏会发布新的分析器主要版本。
    • 优点:无需额外维护分析器,保持分析器代码简洁。
    • 缺点:增加风险及缓解风险的工作量。

若不确定应遵循哪条路径,请联系 security-report-schemas 维护者

容器镜像的位置

安全分析器的容器镜像发布于两个位置:

  • 官方支持镜像 位于 registry.gitlab.com/security-products 命名空间下,例如:

    registry.gitlab.com/security-products/semgrep:5
  • 临时开发镜像 位于项目命名空间下,例如:

    registry.gitlab.com/gitlab-org/security-products/analyzers/semgrep/tmp:d27d44a9b33cacff0c54870a40515ec5f2698475

官方支持的镜像

我们安全模板引用的官方支持镜像的位置是:

registry.gitlab.com/security-products/<ANALYZER-NAME>:<TAG>

例如,SAST.gitlab-ci.yml 模板中 semgrep-sast 作业引用了容器镜像 registry.gitlab.com/security-products/semgrep:5

若要将镜像推送到该位置,请执行以下操作:

  1. https://gitlab.com/security-products/<ANALYZER-NAME> 中创建一个新项目。

    例如:https://gitlab.com/security-products/semgrep

    此项目的镜像将被发布到 registry.gitlab.com/security-products/<ANALYZER-NAME>:<TAG>

    例如:registry.gitlab.com/security-products/semgrep:5

  2. https://gitlab.com/security-products/<ANALYZER-NAME> 项目进行如下配置:

    1. 添加以下权限:

    2. 配置以下项目设置:

      • 设置 → 常规 → 可见性、项目功能、权限
        • 项目可见性
          • 公开
        • 附加选项
          • 用户可以请求访问
            • 禁用
        • 问题
          • 禁用
        • 仓库
          • 仅限项目成员
          • 合并请求
            • 禁用
          • 派生项目
            • 禁用
          • Git 大文件存储(LFS)
            • 禁用
          • CI/CD
            • 禁用
        • 容器注册表
          • 有访问权限的所有人
        • 分析需求安全和合规维基片段包注册表模型实验模型注册表页面监控环境特性标志基础设施发布GitLab Duo
          • 禁用
  3. 为位于 https://gitlab.com/gitlab-org/security-products/analyzers/<ANALYZER_NAME>分析器项目配置以下选项:

    1. 将通配符 v* 添加为受保护的标签

      确保 gl-service-dev-secure-analyzers-automation 服务账号已明确添加到 允许创建 受保护标签的账户列表中。这是为了让 upsert git tag 作业能够为分析器项目创建新的发布版本。

    2. 将通配符 v* 添加为受保护的分支

    3. CI/CD 环境变量

      务必屏蔽和隐藏 SEC_REGISTRY_PASSWORD 变量。

      SEC_REGISTRY_IMAGE registry.gitlab.com/security-products/$CI_PROJECT_NAME
      SEC_REGISTRY_USER gl-service-dev-secure-analyzers-automation
      SEC_REGISTRY_PASSWORD gl-service-dev-secure-analyzers-automation 用户的个人访问令牌。向管理员申请配置此令牌值。

      以上变量由 ci-templates 项目中的 tag_image.sh 脚本用于将容器镜像推送到 registry.gitlab.com/security-products/<ANALYZER-NAME>:<TAG>

      参见 semgrep CI/CD 变量 示例。

临时开发镜像

临时开发镜像的位置如下:

registry.gitlab.com/gitlab-org/security-products/analyzers/<ANALYZER-NAME>/tmp:<TAG>

例如,semgrep 分析器的一个开发镜像如下:

registry.gitlab.com/gitlab-org/security-products/analyzers/semgrep/tmp:7580d6b037d93646774de601be5f39c46707bf04

为了限制拥有写入权限的人数,位于 https://gitlab.com/gitlab-org/security-products/analyzers/<ANALYZER-NAME> 的开发项目的容器注册表必须通过配置以下项目功能和权限设置设为私有:

  • 设置 -> 常规 -> 可见性、项目功能、权限
    • 容器注册表
      • 仅限项目成员

Sec Section 中的每个小组负责:

  1. 管理其制品的弃用和移除计划,并为此创建问题。
  2. 在新位置下创建和配置项目。
  3. 配置构建以将发布制品推送到新位置。
  4. 根据自身支持协议移除或保留旧位置的镜像。

容器镜像每日重建

分析器镜像每天都会重建,以确保我们频繁且自动地拉取基础镜像供应商提供的补丁。

此过程仅适用于与当前主版本匹配的 GitLab 版本所使用的镜像。目的不是每天发布一个新版本,而是重建每个活跃的镜像变体并覆盖相应的标签:

  • 主版本.次版本.修订号 镜像标签(例如:4.1.7
  • 主版本.次版本 镜像标签(例如:4.1
  • 主版本 镜像标签(例如:4
  • latest 镜像标签

重建过程的实现方式可能因项目而异,但我们开发 ci-templates 项目 中提供了一个共享的 CI 配置来帮助实现这一点。

向 GitLab 高级 SAST(GLAS)添加新语言支持

本指南帮助工程师评估并向 GLAS 添加新语言支持。这些准则旨在确保扩展语言覆盖时的一致质量,而非作为严格的要求。

语言支持准备就绪标准

根据您的具体语言调整这些准则,同时维护我们的分析器质量标准。

这些准则来自我们为 GLAS 添加 PHP 支持的经验(参见 问题 #514210),有助于确定新语言支持何时准备好投入生产。

质量准备就绪

跨文件分析能力
  • 支持目标语言中最常见的依赖管理模式
  • 支持特定于语言的常见包含机制
检测质量
  • 支持的 CWEs 整体精确率 ≥ 80%
  • 每个支持的 CWE 有全面的测试语料库
  • 针对语言生态系统中流行框架进行测试

覆盖范围准备就绪

基于优先级的覆盖范围
  • 必须覆盖与该语言相关的关键注入漏洞
  • 必须覆盖常见的安全配置错误
  • 必须符合行业标准(OWASP 十大风险、SANS CWE 前 25 名)
  • 关注该语言中常见的高影响漏洞

支持准备就绪

文档要求
  • 语言已列入支持语言文档并进行了描述
  • CWE 覆盖表格更新了新的语言列
  • 所有支持的 CWE 已正确标记
  • 已明确记录已知局限性

性能准备就绪

标准性能指标
  • 中型应用:< 10 分钟
  • 大型应用:启用多核选项后 < 30 分钟
基准定义
  • 定义用于基准测试的有代表性的代码库
  • 包含常用的框架和库

Go 的安全和构建修复

用 Go 实现的安全分析器的 Dockerfile 必须引用 Go 的 MAJOR 版本,而不是 MINOR 修订版。 这确保了用于编译分析器的 Go 版本包含了给定时间点的所有安全修复。 例如,分析器的多阶段 Dockerfile 必须使用 golang:1.15-alpine 镜像来构建分析器 CLI,但不能使用 golang:1.15.4-alpine

当 Go 的 MINOR 修订版发布且包含安全修复时,项目维护者必须检查安全分析器是否需要重新构建。 构建中使用的 Go 版本应出现在对应发布的 build 作业日志中,也可以通过 strings 命令从 Go 二进制文件中提取。

如果分析器的最新镜像使用的是受影响的 Go 版本,则需要进行重建。 要重建镜像,维护者可以:

  • 触发对应稳定版本的 Git 标签的新管道
  • 创建一个新的 Git 标签,其中 BUILD 号递增
  • 触发默认分支的管道,并将 PUBLISH_IMAGES 变量设置为非空值

无论哪种方式,都会构建新的 Docker 镜像,并以相同的镜像标签发布:MAJOR.MINOR.PATCHMAJOR

此工作流假设同一 Go MAJOR 版本的 MINOR 修订版之间完全兼容。如果有兼容性问题,项目管道在运行测试时会失败。在这种情况下,可能需要在 Dockerfile 中引用 Go 的 MINOR 修订版,并记录该例外,直到兼容性问题解决。

由于未在 Dockerfile 中引用,因此 Go 的 MINOR 修订版不会出现在项目变更日志中。

有时使用构建标签是有意义的,因为所做的更改与构建相关,不需要变更日志条目。例如,将 Docker 镜像推送到新的注册表位置。

用于重建的 Git 标签

当创建新的 Git 标签以重建分析器时,新标签具有与之前相同的 MAJOR.MINOR.PATCH 版本,但 BUILD 号(如 semver 所定义)会递增。

例如,如果分析器的最新发布是 v1.2.3,且对应的 Docker 镜像使用受影响的 Go 版本构建,则维护者创建 Git 标签 v1.2.3+1 以重建镜像。如果最新发布是 v1.2.3+1,则他们创建 v1.2.3+2

构建号会自动从镜像标签中移除。例如,在 gemnasium 项目中创建 Git 标签 v1.2.3+1 会触发管道重建镜像,并将其作为 gemnasium:1.2.3 推送。

用于重建的 Git 标签有一条简单的消息,解释为什么需要新构建。例如:Rebuild with Go 1.15.6。该标签没有发布说明,也不会创建发布。

要创建新的 Git 标签以重建分析器,请遵循以下步骤:

  1. 创建新的 Git 标签并提供消息

    git tag -a v1.2.3+1 -m "Rebuild with Go 1.15.6"
  2. 将标签推送到仓库

    git push origin --tags
  3. 新的 Git 标签管道将被触发,新镜像将被构建并标记。

  4. 运行 master 分支的新管道,以运行完整的测试套件并为新标记的镜像生成新的漏洞报告。这是必要的,因为上述第 3. 步触发的发布管道只运行一部分测试,例如不执行 Container Scanning 分析。

每月发布流程

这应该在每个月的18日完成。不过,这是一个软截止日期,在几天后完成也没有问题。

首先,使用此仓库中的脚本创建一个新的发布issue:./scripts/release_issue.rb MAJOR.MINOR。 该issue将引导你完成整个发布过程。一般来说,你需要执行以下任务:

依赖更新

分析器源代码中使用到的所有依赖项和上游扫描器(如果有)都会按月更新,主要包括安全修复和非破坏性变更。

SAST和Secret Detection

SAST和Secret Detection团队使用一个内部工具(SastBot)来自动化SAST和基于管道的Secret Detection分析器的依赖管理。SastBot会在每个月的8日生成MR,并将分配任务给团队成员进行审核推进。有关该过程的详细信息,请参阅依赖更新自动化

SastBot需要不同的访问令牌用于每个作业。它在运行计划流水线作业时使用DEP_GITLAB_TOKEN环境变量来检索令牌。

计划流水线 令牌来源 角色 范围 DEP_GITLAB_TOKEN令牌配置位置 令牌过期时间
Merge Request Metadata Update security-products/analyzers developer api 设置 > CI/CI变量部分(已掩码、受保护、隐藏) Jul 25, 2026
Release Issue Creation security-products/release 项目 planner api 计划流水线作业的配置部分 Jul 28, 2026
Analyzers sast-bot developer api 计划流水线作业的配置部分 Jul 28, 2026