安全部分分析器开发
分析器以Docker镜像的形式发布,在CI管道环境中执行。本指南介绍了跨分析器的开发和测试实践。
共享模块
分析器之间共享了许多用于通用行为和接口的Go模块:
commandGo包实现了CLI接口。common项目提供了用于日志记录、证书处理和目录搜索功能的杂项共享模块。reportGo包的Report和Finding结构体序列化JSON报告。template项目为新分析器提供脚手架。
如何使用分析器
分析器以Docker镜像的形式发布。例如,要运行Semgrep Docker镜像扫描工作目录:
-
进入要扫描的源代码目录。
-
运行
docker login registry.gitlab.com并提供用户名以及具有至少read_registry权限的个人访问令牌或项目访问令牌。 -
运行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 -
Docker容器会在挂载的项目目录中生成一份报告,报告文件名对应分析器类别。例如,SAST会生成一个名为
gl-sast-report.json的文件。
分析器开发
要更新分析器:
- 修改Go源代码。
- 构建新的Docker镜像。
- 针对测试项目运行分析器。
- 比较生成的报告与预期结果。
以下是创建名为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你也可以为自己的环境编译二进制文件并在本地运行,但由于分析器的运行时依赖缺失,analyze和run可能无法正常工作。
以下是基于SpotBugs的示例:
go build -o analyzer
./analyzer search test/fixtures
./analyzer convert test/fixtures/app/spotbugsXml.Xml > ./gl-sast-report.json安全阶段 CI/CD 模板和组件
安全阶段负责维护以下 CI/CD 模板和组件:
- 组成分析
- 静态分析(SAST)
- 秘密检测
- CI/CD 模板
- CI/CD 组件
对您组的 CI/CD 模板和组件所做的更改必须始终同步,并且您还必须确定这些更改是否需要应用到最新的 CI/CD 模板上。
分析器也在用于离线环境的 Secure-Binaries.gitlab-ci.yml 文件中被引用。进行更改时,请确保此文件也保持同步。
执行条件
启用SAST 需要在 GitLab CI/CD 配置中包含一个预定义的 模板。
以下独立标准决定了哪个分析器需要在项目中运行:
- SAST 模板使用
rules:exists来确定基于某些文件的存在性来运行哪个分析器。例如,Brakeman 分析器 在存在.rb文件和Gemfile时运行。 - 每个分析器在实际分析之前会运行可定制的 匹配接口。例如:Flawfinder 检查 C/C++ 文件。
- 对于一些运行在通用文件扩展名上的分析器,有一个基于 CI/CD 变量的检查。例如:Kubernetes 清单是用 YAML 编写的,所以 Kubesec 仅在设置了
SCAN_KUBERNETES_MANIFESTS为 true 时运行。
第 1 步有助于防止计算配额的浪费,这些配额会被用于运行不适合项目的分析器。然而,由于 技术限制,它不能用于大型项目。因此,第 2 步作为最终检查,确保不匹配的分析器能够提前退出。
如何测试分析器
视频演示了依赖扫描分析器如何使用 下游管道 功能通过测试项目来测试分析器:
Sec 如何利用 GitLab 的下游管道功能端到端测试分析器
测试本地更改
若要测试共享模块(如 command 或 report)的本地更改,你可以使用
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 配合:
- 将
command的内容复制到分析器的目录中。cp -r /path/to/command path/to/analyzer/command。 - 在分析器的
Dockerfile中添加一条复制语句:COPY command /command。 - 更新
replace语句以确保它与上述步骤中COPY语句的目标位置匹配:replace gitlab.com/gitlab-org/security-products/analyzers/command/v3 => /command
测试容器编排兼容性
用户可能使用除Docker以外的工具来编排其容器并运行分析器,例如containerd、Podman或skopeo。为确保与这些工具的兼容性,我们通过计划管道定期测试所有分析器。如果测试失败,会触发Slack警报。
为避免在构建分析器Docker镜像时出现兼容性问题,请使用OCI媒体类型,而不是默认的专有Docker媒体类型。
除定期测试外,我们还确保ci-templates仓库用户的兼容性:
-
使用
ci-templatesdocker-test.yml模板的分析器包含tests,以确保我们的Docker镜像在与支持的Docker工具配合下正常运行。这些测试在Merge Request管道和计划管道中执行,若镜像破坏了支持的Docker工具,则会阻止镜像发布。
-
ci-templatesdocker.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镜像标签。手动任务可重写对应的Major和latest镜像标签,使其指向此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 应用程序中没有对应组件的新组件,可以在任何时候发布。在组件与现有应用集成之前,不应因 我们的标准发布周期和流程 而阻塞迭代。
手动发布流程
- 确保
CHANGELOG.md中新分析器的条目正确。 - 确保发布源(通常是
master或main分支)有通过流水线。 - 通过项目窗口左侧的 Deployments 菜单选择分析器项目的 Releases 子菜单来创建新发布。
- 选择 New release 打开 New Release 页面。
- 在 Tag name 下拉框中,输入与
CHANGELOG.md中相同的版本,例如v2.4.2,并选择创建标签的选项(此处为Create tag v2.4.2)。 - 在 Release title 文本框中输入上述相同版本,例如
v2.4.2。 - 在
Release notes文本框中,复制粘贴CHANGELOG.md中对应版本的说明。 - 其他设置保持默认值。
- 选择 Create release。
- 在 Tag name 下拉框中,输入与
完成上述流程并创建新发布后,将使用上述提供的 Tag name 创建新的 Git 标签。这会触发带有给定标签版本的新流水线,并构建新的分析器 Docker 镜像。
如果分析器使用了 analyzer.yml 模板,则上述 New release 流程触发的流水线会自动标记并部署新版本的分析器 Docker 镜像。
如果分析器未使用 analyzer.yml 模板,则需要手动标记并部署新版本的分析器 Docker 镜像:
- 通过项目窗口左侧的 CI/CD 菜单选择 Pipelines 子菜单。
- 当前应有一个正在运行的新流水线,使用之前相同的标签,例如
v2.4.2。 - 流水线完成后,将处于
blocked状态。 - 选择窗口右侧的
Manual job播放按钮,并选择tag version以标记并部署新版本的分析器 Docker 镜像。
请根据你的最佳判断决定何时创建 Git 标签,这将触发发布作业。如果你无法决定,请征求他人的意见。
自动发布流程
在使用自动发布流程之前,必须执行以下操作:
- 将
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_TOKENCI/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 标签自动触发流水线。此流水线发布分析器的latest、major、minor和patchDocker 镜像。
自动发布过程中使用的服务账户
| 键 | 值 |\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 之前通过以下步骤轮换:
-
以
gl-service-dev-secure-analyzers-automation用户身份登录。该账户的管理员列表可在服务账户访问请求 中找到。
管理员可在共享的 GitLab
1password保险箱中找到登录凭证。 -
为
gl-service-dev-secure-analyzers-automation服务账户创建一个新的个人访问令牌,范围为api。 -
将共享 GitLab
1password保险箱中GitLab API Token - gl-service-dev-secure-analyzers-automation账户的password字段更新为步骤 2 中创建的新个人访问令牌,并将Expires at字段设置为令牌到期时间。 -
更新服务账户用于自动发布过程 表格中
GITLAB_TOKEN字段的到期日期。 -
将以下变量设置为步骤 2 中创建的新个人访问令牌:
对以下变量进行屏蔽和隐藏 至关重要。
-
gitlab-org/security-products/analyzers组的GITLAB_TOKENCI/CD 变量(链接)。这使得
gitlab-org/security-products/analyzers命名空间下的所有项目都能继承此GITLAB_TOKEN值。 -
gitlab-org/security-products/ci-templates项目的GITLAB_TOKENCI/CD 变量(链接)。此处必须显式配置,因为
ci-templates项目未嵌套在gitlab-org/security-products/analyzers命名空间下,因此不会继承GITLAB_TOKEN值。ci-templates项目需要GITLAB_TOKEN来允许某些脚本执行 API 调用。待允许 JOB-TOKEN 访问 CI/lint 端点 完成后,此步骤可移除。 -
gitlab-org/secure/tools/security-triage-automation项目的GITLAB_TOKENCI/CD 变量(链接)。此处必须显式配置,因为
security-triage-automation项目未嵌套在gitlab-org/security-products/analyzers命名空间下,因此不会继承GITLAB_TOKEN值。 -
gitlab-advanced-sast项目的SEC_REGISTRY_PASSWORDCI/CD 变量(链接)。这使得我们的标签脚本 能从开发项目
registry.gitlab.com/gitlab-org/security-products/analyzers/<analyzer-name>/tmp的私有容器注册表中拉取,并推送到公开可访问的容器注册表registry.gitlab.com/security-products/<analyzer-name>。
-
发布分析器后的步骤
-
分析器的 Docker 镜像新版本标记并部署后,使用对应的测试项目进行测试。
-
在相关组 Slack 频道宣布发布。示例如下:
提醒:我刚刚发布了
ANALYZER_NAMEANALYZER_VERSION。LINK_TO_RELEASE
切勿删除已推送的 Git 标签,因为这些标签很可能被 Go 包注册表使用或缓存。
回溯关键修复或补丁
要将关键修复或补丁回溯到早期版本,请按照以下步骤操作。
- 如果不存在,从你要回溯修复的目标标签创建一个新分支。
- 例如,如果最新稳定标签是
v4,而你正在将修复回溯到v3,则创建一个名为v3的新分支。
- 例如,如果最新稳定标签是
- 提交一个针对你刚创建的分支的合并请求。
- 批准后,将该合并请求合并到该分支。
- 为该分支创建一个新标签。
- 如果分析器启用了自动发布流程,则会发布一个新版本。
- 如果没有,你必须遵循手动发布流程来发布新版本。
- 注意:发布流水线会覆盖最新的
edge标签,因此最近的发布流水线的tag edge作业可能需要重新运行,以避免该标签的回归。
为大版本发布准备分析器
此过程适用于以下组:
其他组负责记录自己的大版本发布流程。
根据大版本发布是否包含破坏性变更,选择以下一种情况:
无破坏性变更的大版本发布
假设当前分析器版本为 v{N}:
- 配置受保护的标签和分支。
- 在大版本的里程碑期间,当没有更多更改需要合并到
default分支时:-
从
default分支创建一个v{N}分支。 -
在
default分支中创建并合并一个新的合并请求,其中仅包含对CHANGELOG.md文件的以下更改:## v{N+1}.0.0 - 主要版本发布 (!<MR-ID>)
-
包含破坏性变更的大版本发布
假设当前分析器版本为 v{N}:
-
创建一个新分支
v{N+1}来“暂存”破坏性变更。 -
在大版本里程碑之前的各个里程碑中:
-
将非破坏性变更合并到
default分支(即master或main) -
将破坏性变更合并到
v{N+1}分支,并为每个变更在CHANGELOG.md文件中创建一个单独的release candidate条目:## v{N+1}.0.0-rc.0 - 某些破坏性变更 (!123)使用
发布候选版允许我们在一次主要版本更新中发布所有破坏性变更,这符合语义化版本指南的要求,即仅在主要版本更新中进行破坏性变更。
-
-
在大版本的里程碑期间,当没有更多更改需要合并到
default或v{N+1}分支时:-
从
default分支创建一个v{N}分支。 -
在
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) -
创建一个合并请求,将
v{N+1}分支中的所有破坏性变更合并到default分支。 -
删除
v{N+1}分支,因为它不再需要,因为default分支现在包含了v{N+1}分支的所有变更。
-
配置受保护标签和分支
-
验证 gl-service-dev-secure-analyzers-automation 服务账户是否有权创建受保护标签。
有关更多详情,请参阅 官方支持的镜像 部分的第
3.1步。
配置计划流水线
- 确保存在三个计划流水线(必要时创建),并为所有流水线设置
PUBLISH_IMAGES: true:-
Republish images v{N}(针对v{N}分支)此计划流水线需要被创建
-
Daily build(针对default分支)此计划流水线应已存在
-
Republish images v{N-1}(针对v{N-1}分支)此计划流水线应已存在
-
- 删除
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 部署仍能无错误或警告地摄取安全报告。
可通过以下方式实现:
- 在分析器中实现多架构版本支持。基于 GitLab 版本,分析器使用 GitLab 支持的最新架构版本来生成安全报告。
- 优点:分析器可在运行时决定最优版本。
- 缺点:实现工作量增加且复杂度提高。
- 发布新的分析器主要版本。未包含最新
MODEL架构版本的实例继续使用生成MODEL-1版本报告的分析器版本。- 优点:保持分析器代码简洁。
- 缺点:需维护额外的分析器版本。
- 延迟使用新架构。这依赖于
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。
若要将镜像推送到该位置,请执行以下操作:
-
在
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 -
对
https://gitlab.com/security-products/<ANALYZER-NAME>项目进行如下配置:-
添加以下权限:
-
维护者:
@gitlab-org/secure/managers,@gitlab-org/govern/managers -
开发者:@gl-service-dev-secure-analyzers-automation
这是为了允许自动发布过程中使用的服务账号 将镜像推送到
registry.gitlab.com/security-products/<ANALYZER-NAME>:<TAG>所必需的。
-
-
配置以下项目设置:
设置 → 常规 → 可见性、项目功能、权限项目可见性公开
附加选项用户可以请求访问禁用
问题禁用
仓库仅限项目成员合并请求禁用
派生项目禁用
Git 大文件存储(LFS)禁用
CI/CD禁用
容器注册表有访问权限的所有人
分析、需求、安全和合规、维基、片段、包注册表、模型实验、模型注册表、页面、监控、环境、特性标志、基础设施、发布、GitLab Duo禁用
-
-
为位于
https://gitlab.com/gitlab-org/security-products/analyzers/<ANALYZER_NAME>的分析器项目配置以下选项:-
将通配符
v*添加为受保护的标签。确保 gl-service-dev-secure-analyzers-automation 服务账号已明确添加到
允许创建受保护标签的账户列表中。这是为了让upsert git tag作业能够为分析器项目创建新的发布版本。 -
将通配符
v*添加为受保护的分支。 -
务必屏蔽和隐藏
SEC_REGISTRY_PASSWORD变量。键 值 SEC_REGISTRY_IMAGEregistry.gitlab.com/security-products/$CI_PROJECT_NAMESEC_REGISTRY_USERgl-service-dev-secure-analyzers-automationSEC_REGISTRY_PASSWORDgl-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 中的每个小组负责:
- 管理其制品的弃用和移除计划,并为此创建问题。
- 在新位置下创建和配置项目。
- 配置构建以将发布制品推送到新位置。
- 根据自身支持协议移除或保留旧位置的镜像。
容器镜像每日重建
分析器镜像每天都会重建,以确保我们频繁且自动地拉取基础镜像供应商提供的补丁。
此过程仅适用于与当前主版本匹配的 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.PATCH 和 MAJOR。
此工作流假设同一 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 标签以重建分析器,请遵循以下步骤:
-
创建新的 Git 标签并提供消息
git tag -a v1.2.3+1 -m "Rebuild with Go 1.15.6" -
将标签推送到仓库
git push origin --tags -
新的 Git 标签管道将被触发,新镜像将被构建并标记。
-
运行
master分支的新管道,以运行完整的测试套件并为新标记的镜像生成新的漏洞报告。这是必要的,因为上述第3.步触发的发布管道只运行一部分测试,例如不执行Container Scanning分析。
每月发布流程
这应该在每个月的18日完成。不过,这是一个软截止日期,在几天后完成也没有问题。
首先,使用此仓库中的脚本创建一个新的发布issue:./scripts/release_issue.rb MAJOR.MINOR。
该issue将引导你完成整个发布过程。一般来说,你需要执行以下任务:
-
检查GitLab文档中支持的技术列表。
-
检查vendored CI/CD模板中的CI作业定义是否仍然准确,并且每个工具在执行
docker run时所有ENV变量都已传播到Docker容器中。如有需要,前往对应最后一个Git标签的流水线,并触发控制此镜像构建的手动作业。
依赖更新
分析器源代码中使用到的所有依赖项和上游扫描器(如果有)都会按月更新,主要包括安全修复和非破坏性变更。
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 |