依赖扫描
依赖扫描功能可以在您开发和测试应用程序时,自动查找软件依赖项中的安全漏洞。例如,依赖项扫描可以让您知道您的应用程序是否使用已知易受攻击的外部(开源)库。然后,您可以采取措施保护您的应用程序。
依赖扫描通常被认为是软件组合分析 (SCA) 的一部分。SCA 可以包含检查代码使用的项目的各个方面,这些项目通常包括几乎总是从外部源导入的应用程序和系统依赖项,而不是来自您自己编写的项目。
依赖项扫描可以在你应用程序生命周期的开发阶段运行。每次流水线运行时候,都会比较源分支和目标分支病识别漏洞。漏洞和其严重程度都会列在合并请求中,这能够让你在将代码变更提交之前正确识别你应用程序中的风险。还可以通过持续漏洞扫描来识别漏洞。
极狐GitLab 同时提供依赖项扫描和容器扫描来确保能够覆盖所有的依赖类型。为了尽可能覆盖更多的风险区域,我们鼓励你使用我们所有的安全扫描器。对于这些功能的对比,可以查看依赖项和容器扫描对比。
支持的语言和包管理器
依赖扫描自动检测仓库中使用的语言,运行与检测到的语言匹配的所有分析器,通常不需要自定义分析器的选择。我们建议不要指定分析器,以便您自动使用完整选择从而获得最佳覆盖范围,避免在出现弃用或删除时进行调整。
但是,您可以使用变量 DS_EXCLUDED_ANALYZERS
覆盖选择。
语言检测依赖于 CI 作业 rules
,并从仓库的根目录中搜索最多两个目录级别。例如,如果仓库包含Gemfile
、api/Gemfile
或 api/client/Gemfile
,则启用 gemnasium-dependency_scanning
作业,但如果唯一支持的依赖文件是 api/v1/client/Gemfile
,则不会启用。
对于 Java 和 Python,当检测到支持的依赖文件时,依赖扫描会尝试构建项目并执行一些 Java 或 Python 命令以获取依赖项列表。对于所有其他项目,无需先构建项目,即可解析锁定文件以获取依赖项列表。
当检测到支持的依赖文件时,将分析所有依赖项,包括传递依赖项。分析的嵌套或传递依赖项的深度没有限制。
支持以下语言和依赖项管理器:
语言 | 语言版本 | 软件包管理器 | 支持的文件 | 处理多个文件? |
---|---|---|---|---|
.NET | 所有版本 | NuGet | packages.lock.json |
Y |
C# | ||||
C | 所有版本 | Conan | conan.lock |
Y |
C++ | ||||
Go | 所有版本 | Go |
|
Y |
Java and Kotlin | 8 LTS, 11 LTS, 17 LTS, or 21 LTS1 | Gradle2 |
|
N |
Maven6 | pom.xml |
N | ||
JavaScript and TypeScript | 所有版本 | npm |
|
Y |
yarn | yarn.lock |
Y | ||
pnpm3 | pnpm-lock.yaml |
Y | ||
PHP | All versions | Composer | composer.lock |
Y |
Python | 3.117 | setuptools8 | setup.py |
N |
pip |
|
N | ||
Pipenv | N | |||
Poetry4 | poetry.lock |
N | ||
Ruby | All versions | Bundler |
|
Y |
Scala | All versions | sbt5 | build.sbt |
N |
Swift | All versions | Swift Package Manager | Package.resolved |
N |
Cocoapods9 | All versions | CocoaPods | Podfile.lock |
N |
-
Java 21 LTS sbt 仅限于版本 1.9.7。当启用 FIPS 模式时,不支持此功能。
-
当启用 FIPS 模式时不支持 Gradle。
-
对于
pnpm
lockfiles 的支持引入于极狐GitLab 15.11</a>。pnpm
lockfiles 不能存储捆绑依赖,所以报告的依赖可能和npm
或yarn
不同。 -
对于具有
poetry.lock
文件的 Poetry 项目的支持引入于极狐GitLab 15.0。 -
对于 sbt 1.0.x 的支持在极狐GitLab 16.8 中被弃用并在极狐GitLab 17.0 中被移除。
-
对低于 3.8.8 以下版本的 Maven 支持已经在极狐GitLab 16.9 中被弃用,并将在极狐GitLab 17.0 中被移除。
-
对于早期 Python 版本的支持在极狐GitLab 16.9 中被弃用。并在极狐GitLab 17.0 中被移除。
-
将
pip
和setuptools
从报告中排除,因为它们是安装程序所必需的。 -
仅有 SBOM,没有公告。
依赖检测
依赖扫描自动检测仓库中使用的语言。所有与检测语言相匹配的分析器都会运行。所以通常没有必须自定义分析的选择。我们不推荐指定分析器以便你可以为最佳覆盖自动使用完整的分析器选择,避免在需要弃用或移除的时候做调整。然而,你可以使用变量 DS_EXCLUDED_ANALYZERS
来进行覆盖选择。
语言检测依赖于 CI 作业 rules
并从存储库的根目录开始,最多搜索两个目录层级。 比如,如果仓库包含 Gemfile
、api/Gemfile
或 api/client/Gemfile
,则 gemnasium-dependency_scanning
作业就会被启动,但如果唯一符合支持条件的依赖项文件是 api/v1/client/Gemfile
,该作业则不会被启用。
对于 Java 和 Python,当检测到支持的依赖文件时,依赖扫描就会尝试构建项目并执行一些 Java 或 Python 命令来获取依赖列表。对于其他所有的项目,lock 文件会被解析以包含依赖列表,而无需先构建项目。
当检测到支持的依赖文件时,所有的依赖,包括传递依赖项在内都要进行分析。对于所分析的嵌套依赖项或传递依赖项的深度没有限制。
如何触发分析器
极狐GitLab 依赖 rules:exists
来启动相关分析器,针对仓库中存在的 Supported files
检测到的语言,如上表所示。
当前的检测逻辑将最大搜索深度限制为两个级别。例如,如果仓库包含 Gemfile.lock
、api/Gemfile.lock
或 api/client/Gemfile.lock
,则启用 gemnasium-dependency_scanning
作业,但如果唯一支持的依赖文件是 api/v1/client/Gemfile.lock
,则不然。
当检测到支持的依赖文件时,将分析所有依赖项,包括传递依赖项。分析的嵌套或传递依赖项的深度没有限制。
分析器
依赖扫描支持如下的基于 Gemnasium 的官方分析器:
gemnasium
gemnasium-maven
gemnasium-python
分析器以 Docker 镜像发布,依赖扫描会为每个分析发布专用的容器。你还可以集成自定义的安全扫描器。
每当 Gemnasium 发布新版本的时候,分析器也会进行更新。
分析器如何获取依赖信息
极狐GitLab 使用如下两种方式中的一种来获取依赖信息:
通过解析 lockfiles 来获取依赖信息
如下软件包管理器使用极狐GitLab 分析器能够处理的 lockfiles 来直接进行解析:
软件包管理器 | 支持的文件格式版本 | 测试软件包管理器版本 |
---|---|---|
Bundler | 不适用 | 1.17.3、2.1.4 |
Composer | 不适用 | 1.x |
Conan | 0.4 | 1.x |
Go | 不适用 | 1.x |
NuGet | v1, v21 | 4.9 |
npm | v1, v2, v32 | 6.x、7.x、9.x |
pnpm | v5, v6, v9 | 7.x、8.x、9.x |
yarn | versions 1, 2, 3, 43 | 1.x、2.x、3.x |
Poetry | v1 | 1.x |
-
对于 NuGet 版本 2 lockfile 的支持引入于极狐GitLab 16.2。
-
对于
lockfileVersion = 3
的支持引入于极狐GitLab 15.7。 -
对于 Yarn 版本 4 的支持引入于GitLab 16.11。
以下功能不支持 Yarn Berry:
包含补丁、工作空间或同时包含这两者的 Yarn 文件依旧会处理,但是这些功能会被忽略。
通过运行软件包管理器来生成可解析的文件来获取依赖信息
要支持如下软件包管理器,极狐GitLab 分析器会进行以下两步:
- 执行软件包管理器或特定的作业来导出依赖信息。
- 解析导出的依赖信息。
软件包管理器 | 预安装的版本 | 测试版本 |
---|---|---|
sbt | 1.6.2 | 1.1.6、1.2.8、1.3.12、1.4.6、1.5.8、1.6.2、1.7.3、1.8.3、1.9.6、1.9.7 |
maven | 3.9.8 | 3.9.81 |
Gradle | 6.7.1</a>2、7.6.4</a>2、8.8</a>2 | 5.6、6.7、6.9、7.6、8.8 |
setuptools | 70.3.0 | >= 70.3.0 |
pip | 24 | 24 |
Pipenv | 2023.11.15 | 2023.11.15</a>3、2023.11.15 |
Go | 1.21 | 1.21</a>4 |
-
此测试使用由
.tool-versions
文件指定的maven
默认版本。 -
Java 的不同版本需要不同版本的 Gradle。上述表中列出的 Gradle 版本都已在分析器中预安装。分析器使用的 Gradle 版本依赖你的项目是否使用
gradlew
文件:-
如果你的项目 没有使用 一个
gradlew
文件,然后分析器会自动切换到预安装 Gradle 版本中的一个,基于DS_JAVA_VERSION
</a> 变量指定的 Java 版本。(默认版本为17
)。对于 Java
8
和11
, Gradle6.7.1
会自动被选择,Java17
使用 Gradle7.6.4
, Java21
使用 Gradle8.8
。 -
如果你的项目 没有使用 一个
gradlew
文件,则分析器镜像中预安装的 Gradle 版本会被忽略,从而使用在gradlew
文件中指定的版本。
-
-
此测试会确实
Pipfile.lock
文件是否存在,Gemnasium 会使用此文件来扫描文件中列出的精确软件包版本。 -
由于
go build
的实现,Go build 会处理需要的网络访问,通过go mod download
或供应商依赖预下来模块缓存。
分析器是如何被触发的
极狐GitLab 依赖于 rules:exists
来启动为检测到的语言启用的相关分析器,这些语言是通过存储库中存在的
支持的文件
来检测的,如上表所示 上表。
当前的检测逻辑将最大搜索深度限制为两级。例如,如果存储库包含 Gemfile.lock
、api/Gemfile.lock
或 api/client/Gemfile.lock
,则 gemnasium-dependency_scanning
作业将被启用,但如果唯一支持的依赖文件是 api/v1/client/Gemfile.lock
,则不会启用。
当检测到支持的依赖文件时,包括传递依赖项在内的所有依赖项都会被分析。对于被分析的嵌套或传递依赖项的深度没有限制。
Python
我们只在检测到需求文件或锁定文件的目录中执行一次安装。依赖关系仅由 gemnasium-python
分析检测到的第一个文件。按以下顺序搜索文件:
-
requirements.txt
、requirements.pip
或requires.txt
用于使用 Pip 的项目。 -
Pipfile
或Pipfile.lock
用于使用 Pipenv 的项目。 -
poetry.lock
用于使用 Poetry 的项目。 - 使用 Setuptools 的项目的
setup.py
。
搜索从根目录开始,如果在根目录中未找到任何构建,则继续搜索子目录。因此,将在子目录中的 Pipenv 文件之前,检测到根目录中的 Poetry 锁定文件。
Java and Scala
我们只在检测到构建文件的目录中执行一个构建。对于包含多个 Gradle、Maven 或 sbt 构建或这些构建的任何组合的大型项目,gemnasium-maven
仅分析检测到的第一个构建文件的依赖关系。构建文件按以下顺序搜索:
-
build.gradle
或build.gradle.kts
用于单个或多项目 Gradle 构建。 -
pom.xml
用于单个或多模块 Maven 项目。 -
build.sbt
用于单个或多项目 sbt 构建。
搜索从根目录开始,如果在根目录中未找到任何构建,则继续搜索子目录。因此,将在子目录中的 Gradle 构建文件之前,检测到根目录中的 sbt 构建文件。
JavaScript
执行以下分析器,每个分析器在处理多个文件时具有不同的行为:
-
Gemnasium
支持多个 lockfile。
-
不支持多个 lockfile。当存在多个 lockfile 时,
Retire.js
会分析在按字母顺序遍历目录树时发现的第一个 lockfile。
从 14.8 版本开始,gemnasium
分析器会扫描支持的 JavaScript 项目,查找供应商库(即检入项目但不受包管理器管理的库)。
Go
支持多个文件。当检测到 go.mod
文件时,分析器会尝试使用最小版本选择。如果遇到非致命错误,分析器会回退到解析可用的 go.sum
文件。对每个检测到的 go.mod
和 go.sum
文件重复该过程。
PHP、C、C++、.NET、C#、Ruby、JavaScript
这些语言的分析器支持多个 lockfile。
支持其它语言
在以下问题中跟踪对其他语言、依赖管理器和依赖文件的支持:
包管理器 | 语言 | 支持的文件 | 扫描工具 |
---|---|---|---|
Poetry | Python | poetry.lock |
Gemnasium |
配置
要启用依赖扫描,您必须包含 Dependency-Scanning.gitlab-ci.yml
模板,其作为极狐GitLab 安装的一部分提供。
启用分析器
先决条件:
-
.gitlab-ci.yml
文件中需要有一个test
阶段。 - 对于自部署的 runner,需要使用
docker
和kubernetes
执行器。 - 如果你正在 JihuLab.com 上使用,则默认启用。
要启用分析器,执行以下几种方式中的一种:
- 启用 Auto DevOps,这会包含依赖扫描。
- 使用预配置的合并请求。
- 创建强制执行依赖扫描的 扫描执行策略。
- 手动编辑
.gitlab-ci.yml
文件。 - 使用 CI/CD 组件
使用预配置的合并请求
此方法会自动准备一个在 .gitlab-ci.yml
文件中包含依赖扫描模板的合并请求。然后你将合并请求合并以启用依赖扫描。
.gitlab-ci.yml
文件或具有少量配置文件的情况下工作良好。如果你有一个负责的极狐GitLab 配置文件,这可能会无法被成功解析,而且可能会发生错误。在这些情况下,请使用手动方法。要启用依赖扫描:
- 在左侧导航栏,选择 搜索或前往 并找到你的项目。
- 选择 安全 > 安全配置。
- 在 依赖扫描 中,选择 配置合并请求。
- 选择 创建合并请求。
- 查看合并请求,然后选择 合并。
流水线现在包含了一个依赖扫描作业。
手动编辑 .gitlab-ci.yml
文件
此方法需要你手动编辑既有的 .gitlab-ci.yml
文件。如果你的极狐GitLab CI/CD 配置文件过于复杂,请使用此方法。
要启用依赖扫描:
- 在左侧导航栏,选择 搜索或前往 并找到你的项目。
- 选择 构建 > 流水线编辑器。
- 如果没有
.gitlab-ci.yml
文件,选择 配置流水线,然后删除示例内容。 -
拷贝并粘贴下面的内容到
.gitlab-ci.yml
文件底部。如果已经存在include
,则仅添加template
行即可。include: - template: Jobs/Dependency-Scanning.gitlab-ci.yml
-
选择 验证 选项卡,然后选择 验证流水线。
消息 模拟完成成功 确认了文件的有效性。
- 完成字段。不要再 分支 字段中使用默认分支。
- 选择 使用这些变更启动新的合并请求,然后选择 提交信息。
- 根据你的标准工作流完成字段,然后选择 创建合并请求。
- 根据你的标准工作流来审核并编辑合并请求,然后选择 合并。
现在流水线就会包含一个依赖扫描作业了。
使用 CI/CD 组件
- 引入于极狐GitLab 17.0。这是一个实验性功能。
- 依赖扫描 CI/CD 组件仅支持 Android 项目。
使用 CI/CD 组件 来执行你应用程序的依赖扫描。对于使用指南,查看组件的 README 文件。
在合并请求流水线中运行作业
自定义分析器行为
要自定义依赖扫描,使用CI/CD 变量。
覆盖依赖扫描作业
要覆盖作业的定义(比如,要修改诸如 variables
或 dependencies
的属性),声明一个和需要覆盖作业相同名称的作业。将此作业放置在模板包含的后面并在其下面指定额外的键值。比如,为 gemnasium
分析器禁用 DS_REMEDIATE
:
include:
- template: Jobs/Dependency-Scanning.gitlab-ci.yml
gemnasium-dependency_scanning:
variables:
DS_REMEDIATE: "false"
要覆盖 dependencies: []
属性,在其上方添加覆盖作业,指向此属性:
include:
- template: Jobs/Dependency-Scanning.gitlab-ci.yml
gemnasium-dependency_scanning:
dependencies: ["build"]
可用的 CI/CD 变量
可以使用环境变量配置依赖扫描。
配置依赖扫描
以下变量允许配置全局依赖扫描设置。
CI/CD 变量 | 描述 |
---|---|
ADDITIONAL_CA_CERT_BUNDLE |
要信任的 CA 证书捆绑包。此处提供的证书包也被其他工具在扫描过程中使用,例如 git 、yarn 或 npm 。查看使用自定义 SSL CA 证书颁发机构,获取更多信息。 |
DS_EXCLUDED_ANALYZERS |
指定要从依赖扫描中排除的分析器(按名称)。有关详细信息,请参阅依赖扫描分析器。 |
DS_EXCLUDED_PATHS |
根据路径从扫描中排除文件和目录,以逗号分隔的 pattern 列表。Pattern 可以是 glob(有关支持的模板,请参阅 doublestar.Match )、文件或文件夹路径(例如,doc、spec ),父目录也匹配 pattern。默认值:"spec,test,tests,tmp" 。 |
DS_IMAGE_SUFFIX |
后缀添加到镜像名称。如果设置为 -fips ,则使用 FIPS-enabled 镜像进行扫描。有关详细信息,请参阅启用 FIPS 的镜像。引入于 14.10 版本。 |
SECURE_ANALYZERS_PREFIX |
覆盖提供官方默认镜像(代理)的 Docker 镜像库的名称。阅读有关自定义分析器的更多信息。 |
SECURE_LOG_LEVEL |
设置最低日志记录级别,输出此日志级别或更高级别的消息,从最高到最低严重性,日志记录级别是:fatal 、error 、warn 、info 、debug 。引入于 13.1 版本,默认值:info 。 |
配置依赖扫描使用的特定分析器
以下变量用于配置特定分析器(用于特定语言/框架)。
CI/CD 变量 | 分析器 | 默认值 | 描述 |
---|---|---|---|
GEMNASIUM_DB_LOCAL_PATH |
gemnasium |
/gemnasium-db |
本地 Gemnasium 数据库的路径。 |
GEMNASIUM_DB_UPDATE_DISABLED |
gemnasium |
"false" |
禁用 gemnasium-db 咨询数据库的自动更新
|
GEMNASIUM_DB_REMOTE_URL |
gemnasium |
用于获取 Gemnasium 数据库的仓库 URL。 | |
GEMNASIUM_DB_REF_NAME |
gemnasium |
master |
远端仓库数据库的分支名称。需要先配置 GEMNASIUM_DB_REMOTE_URL 。 |
DS_REMEDIATE |
gemnasium |
"true" ,FIPS 模式中为 "false"
|
启用易受攻击的依赖项的自动修复。 |
DS_REMEDIATE_TIMEOUT |
gemnasium |
5m |
自动修复超时。 |
GEMNASIUM_LIBRARY_SCAN_ENABLED |
gemnasium |
"true" |
启用检测供应商 JavaScript 库中的漏洞。目前,gemnasium 利用 Retire.js 来完成这项工作。引入于 14.8 版本。 |
DS_INCLUDE_DEV_DEPENDENCIES |
gemnasium |
"true" |
当设置为 false 时,不报告开发依赖项及其漏洞。仅支持 Composer、NPM 和 Poetry 项目。引入于 15.1 版本。 |
GOOS |
gemnasium |
"linux" |
编译 Go 代码的操作系统。 |
GOARCH |
gemnasium |
"amd64" |
编译 Go 代码的处理器架构。 |
GOFLAGS |
gemnasium |
传递给 go build 工具的标志。 |
|
GOPRIVATE |
gemnasium |
要从源中获取的 glob pattern 和前缀列表。阅读 Go 私有模块文档,了解更多信息。 | |
DS_JAVA_VERSION |
gemnasium-maven |
17 |
Java 版本。可用版本:8 、11 、17 。 |
MAVEN_CLI_OPTS |
gemnasium-maven |
"-DskipTests --batch-mode" |
分析器传递给 maven 的命令行参数列表。 |
GRADLE_CLI_OPTS |
gemnasium-maven |
分析器传递给 gradle 的命令行参数列表。 |
|
GRADLE_PLUGIN_INIT_PATH |
gemnasium-maven |
"gemnasium-init.gradle" |
指定 Gradle 初始化脚本的路径。初始化脚本必须包含 allprojects { apply plugin: 'project-report' } 以确保兼容性。 |
DS_GRADLE_RESOLUTION_POLICY |
gemnasium-maven |
"failed" |
控制 Gradle 依赖解决限制。接受 "none" 以允许部分结果,或当任何依赖解析失败时使用 "failed" 以让扫描失败。 |
SBT_CLI_OPTS |
gemnasium-maven |
分析器传递给 sbt 的命令行参数列表。 |
|
PIP_INDEX_URL |
gemnasium-python |
https://pypi.org/simple |
Python 包索引的基本 URL。 |
PIP_EXTRA_INDEX_URL |
gemnasium-python |
除了 PIP_INDEX_URL 之外要使用的包索引的额外 URL 数组,逗号分隔。警告: 使用此环境变量时请阅读以下安全注意事项。 |
|
PIP_REQUIREMENTS_FILE |
gemnasium-python |
要扫描的 Pip 需求文件。 | |
PIPENV_PYPI_MIRROR |
gemnasium-python |
如果设置,则使用镜像覆盖 Pipenv 使用的 PyPi 索引。 | |
DS_PIP_VERSION |
gemnasium-python |
强制安装特定的 pip 版本(例如:"19.3" ),否则使用 Docker 镜像中安装的 pip。 |
|
DS_PIP_DEPENDENCY_PATH |
gemnasium-python |
从中加载 Python pip 依赖项的路径。 |
其它变量
前面的表格并不是可以使用的所有变量的详尽列表,包含我们支持和测试的所有特定极狐GitLab 和分析器变量。有许多变量,例如环境变量,您可以传入并且它们会起作用。这是一个很大的列表,其中许多我们可能不知道,因此没有记录在案。
例如,要将非 GitLab 环境变量 HTTPS_PROXY
传递给所有依赖扫描作业,请将其设置为 .gitlab-ci.yml
文件中的自定义 CI/CD 变量,如下所示:
variables:
HTTPS_PROXY: "https://squid-proxy:3128"
或者,我们可以在特定的工作中使用它,比如依赖扫描:
dependency_scanning:
variables:
HTTPS_PROXY: $HTTPS_PROXY
因为我们没有测试所有你可能找到的变量,所以有些能工作,有些不能工作。
自定义 TLS 证书颁发机构
依赖扫描允许为 SSL/TLS 连接使用自定义 TLS 证书,而不是使用分析器镜像中默认交付的证书。
对于自定义证书颁发机构的支持引入于以下版本:
Analyzer | Version |
---|---|
gemnasium |
v2.8.0 |
gemnasium-maven |
v2.9.0 |
gemnasium-python |
v2.7.0 |
使用自定义 SSL CA 证书颁发机构
您可以使用 ADDITIONAL_CA_CERT_BUNDLE
CI/CD 变量来配置自定义 SSL CA 证书颁发机构。ADDITIONAL_CA_CERT_BUNDLE
值应包含 X.509 PEM 公钥证书的文本表示形式。
例如,要在 .gitlab-ci.yml
文件中配置此值,请使用以下命令:
variables:
ADDITIONAL_CA_CERT_BUNDLE: |
-----BEGIN CERTIFICATE-----
MIIGqTCCBJGgAwIBAgIQI7AVxxVwg2kch4d56XNdDjANBgkqhkiG9w0BAQsFADCB
...
jWgmPqF3vUbZE0EyScetPJquRFRKIesyJuBFMAs=
-----END CERTIFICATE-----
认证私有 Maven 仓库
要使用需要认证的私有 Maven 仓库,你应该将凭据存储在 CI/CD 变量中并在你的 Maven 设置文件中引用它们。不要将凭据添加到你的 .gitlab-ci.yml
文件中。
要认证私有 Maven 仓库:
-
在你的项目设置中添加
MAVEN_CLI_OPTS
CI/CD 变量,将值设置为你的凭据。比如,如果你的用户名是
myuser
,密码是verysecret
:类型 Key Value 变量 MAVEN_CLI_OPTS
--settings mysettings.xml -Drepository.password=verysecret -Drepository.user=myuser
-
使用你的服务器配置来创建一个 Maven 设置文件。
比如,将如下内容添加到
mysettings.xml
文件中。此文件会在MAVEN_CLI_OPTS
CI/CD 变量中被引用。<!-- mysettings.xml --> <settings> ... <servers> <server> <id>private_server</id> <username>${private.username}</username> <password>${private.password}</password> </server> </servers> </settings>
FIPS-enabled 镜像
GitLab 还提供 FIPS-enabled Red Hat UBI版本的 Gemnasium 镜像。当 GitLab 实例中启用 FIPS 模式时,Gemnasium 扫描作业会自动使用 FIPS-enabled 镜像。要手动切换到 FIPS-enabled 镜像,请将变量 DS_IMAGE_SUFFIX
设置为 "-fips"
。
在 FIPS 模式下,不支持 Gradle 项目的依赖扫描和 Yarn 项目的自动修复。
FIPS-enabled 镜像基于 RedHat 的 UBI 微型。它们没有诸如 dnf
或 microdnf
的软件包管理器因此无法在运行时安装系统软件包。
输出
依赖扫描会生成如下输出:
- 依赖扫描报告:包含在依赖中检测到的所有漏洞详情。
- CycloneDX 软件物料清单:每个受支持且检测到的 lock 和构建文件的软件物料清单。
依赖扫描报告
依赖扫描会输出一个包含所有漏洞详情的报告。此报告处理后展示在 UI 上。报告还会输出为依赖扫描作业的产物,名为 gl-dependency-scanning-report.json
。
对于依赖扫描报告的更多详情,可以查看:
CycloneDX 软件物料清单
- 一般可用于 15.7 版本。
依赖扫描工具为它检测到的每个支持的锁定或构建文件输出一个 CycloneDX Software Bill of Materials (SBOM)。
这些 CycloneDX SBOM 会是:
- 被命名为
gl-sbom-<package-type>-<package-manager>.json
。 - 作为依赖扫描作业可用的作业产物。
- 保存在和 lock 或构建文件的同级目录下。
例如,如果您的项目具有以下结构:
.
├── ruby-project/
│ └── Gemfile.lock
├── ruby-project-2/
│ └── Gemfile.lock
├── php-project/
│ └── composer.lock
└── go-project/
└── go.sum
然后 Gemnasium 扫描器生成以下 CycloneDX SBOM:
.
├── ruby-project/
│ ├── Gemfile.lock
│ └── gl-sbom-gem-bundler.cdx.json
├── ruby-project-2/
│ ├── Gemfile.lock
│ └── gl-sbom-gem-bundler.cdx.json
├── php-project/
│ ├── composer.lock
│ └── gl-sbom-packagist-composer.cdx.json
└── go-project/
├── go.sum
└── gl-sbom-go-go.cdx.json
合并多个 CycloneDX SBOM
你可以使用 CI/CD 作业来合并多个 CycloneDX SBOM 到单个 SBOM 中。极狐GitLab 使用 CycloneDX 属性,在每个 CycloneDX SBOM 的元数据中存储实现特定的详细信息,例如构建和锁定的文件位置。如果多个 CycloneDX SBOM 合并在一起,则此信息将从生成的合并文件中删除。
比如,如下的 .gitlab-ci.yml
演示了 CycloneDX 文件是如何被合并的,而且结果文件是经过验证的。
stages:
- test
- merge-cyclonedx-sboms
include:
- template: Security/Dependency-Scanning.gitlab-ci.yml
merge cyclonedx sboms:
stage: merge-cyclonedx-sboms
image:
name: cyclonedx/cyclonedx-cli:0.24.0
entrypoint: [""]
script:
- find . -name "gl-sbom-*.cdx.json" -exec /cyclonedx merge --output-file gl-sbom-all.cdx.json --input-files "{}" +
artifacts:
paths:
- gl-sbom-all.cdx.json
离线环境
对于受限环境下的私有化部署实例,要成功运行依赖扫描作业,需要做一些调整。更多详情,可查阅离线环境。
先决条件
要在离线环境下运行依赖扫描,你必须要:
- 使用
docker
或kubernetes
执行器的极狐GitLab Runner - 依赖扫描分析器镜像的本地拷贝
分析器镜像的本地拷贝
要使用所有支持的语言和框架的依赖扫描:
-
从
registry.gitlab.com
导入以下默认的依赖扫描分析器镜像到 你的本地Docker容器注册表中:registry.gitlab.com/security-products/gemnasium:5 registry.gitlab.com/security-products/gemnasium:5-fips registry.gitlab.com/security-products/gemnasium-maven:5 registry.gitlab.com/security-products/gemnasium-maven:5-fips registry.gitlab.com/security-products/gemnasium-python:5 registry.gitlab.com/security-products/gemnasium-python:5-fips
将Docker镜像导入到本地离线Docker注册表中的过程取决于 你的网络安全策略。请与你的IT人员联系,了解外部资源可以被导入或临时访问的接受和批准的过程。 这些扫描器会定期更新 新的定义,你可能想定期下载它们。
-
配置GitLab CI/CD以使用本地分析器。
将CI/CD变量
SECURE_ANALYZERS_PREFIX
的值设置为你的本地Docker注册表 - 在 这个例子中,docker-registry.example.com
。include: - template: Jobs/Dependency-Scanning.gitlab-ci.yml variables: SECURE_ANALYZERS_PREFIX: "docker-registry.example.com/analyzers"
访问GitLab Advisory Database
GitLab Advisory Database 是
gemnasium
, gemnasium-maven
, 和 gemnasium-python
分析器使用的漏洞数据源。这些分析器的Docker镜像包含数据库的克隆。
在开始扫描之前,克隆会与数据库同步,以确保分析器拥有最新的漏洞数据。
在离线环境中,默认的GitLab Advisory Database主机不能被访问。 相反,你必须在GitLab运行器可以访问的地方托管数据库。你还必须根据自己的计划手动更新数据库。
托管数据库的可用选项是:
使用GitLab Advisory Database的克隆
使用GitLab Advisory Database的克隆是推荐的,因为这是最有效的方法。
要托管GitLab Advisory Database的克隆:
- 将GitLab Advisory Database克隆到GitLab运行器可以通过HTTP访问的主机上。
- 在你的
.gitlab-ci.yml
文件中,设置CI/CD变量GEMNASIUM_DB_REMOTE_URL
的值为 Git存储库的URL。
例如:
variables:
GEMNASIUM_DB_REMOTE_URL: https://users-own-copy.example.com/gemnasium-db.git
使用GitLab Advisory Database 的副本
使用 GitLab Advisory Database 的副本需要你托管一个存档文件,该文件将被分析器下载。
要使用 GitLab Advisory Database 的副本:
- 从 GitLab Advisory Database 下载一个存档文件到GitLab运行器可以通过HTTP访问的主机上。存档文件位于
https://gitlab.com/gitlab-org/security-products/gemnasium-db/-/archive/master/gemnasium-db-master.tar.gz
。 -
更新你的
.gitlab-ci.yml
文件。- 设置CI/CD变量
GEMNASIUM_DB_LOCAL_PATH
使用数据库的本地副本。 - 设置CI/CD变量
GEMNASIUM_DB_UPDATE_DISABLED
禁用数据库更新。 - 在扫描开始之前下载并提取咨询数据库。
variables: GEMNASIUM_DB_LOCAL_PATH: ./gemnasium-db-local GEMNASIUM_DB_UPDATE_DISABLED: "true" dependency_scanning: before_script: - wget https://local.example.com/gemnasium_db.tar.gz - mkdir -p $GEMNASIUM_DB_LOCAL_PATH - tar -xzvf gemnasium_db.tar.gz --strip-components=1 -C $GEMNASIUM_DB_LOCAL_PATH
- 设置CI/CD变量
使用Gradle项目的代理
Gradle wrapper脚本不读取 HTTP(S)_PROXY
环境变量。见这个上游问题。
要使Gradle wrapper脚本使用代理,可以使用 GRADLE_CLI_OPTS
CI/CD变量指定选项:
variables:
GRADLE_CLI_OPTS: "-Dhttps.proxyHost=squid-proxy -Dhttps.proxyPort=3128 -Dhttp.proxyHost=squid-proxy -Dhttp.proxyPort=3128 -Dhttp.nonProxyHosts=localhost"
使用Maven项目的代理
Maven不读取 HTTP(S)_PROXY
环境变量。
要使Maven依赖项扫描器使用代理,可以使用 settings.xml
文件(见Maven文档)配置,并通过使用 MAVEN_CLI_OPTS
CI/CD变量来指示Maven使用这个配置:
variables:
MAVEN_CLI_OPTS: "--settings mysettings.xml"
特定语言和包管理器的设置
见以下部分,了解如何为特定语言和包管理器进行配置。
Python (pip)
如果你需要在分析器运行之前安装Python包,你应该在扫描作业的 before_script
中使用 pip install --user
。--user
标志导致项目依赖项被安装在用户目录中。如果你不传递 --user
选项,包将被全局安装,并且它们不会被扫描和列出项目依赖项。
Python (setuptools)
如果你需要在分析器运行之前安装Python包,你应该在扫描作业的 before_script
中使用 python setup.py install --user
。--user
标志导致项目依赖项被安装在用户目录中。如果你不传递 --user
选项,包将被全局安装,并且它们不会被扫描和列出项目依赖项。
当使用自签名证书为你的私有PyPi仓库时,除了上述模板 .gitlab-ci.yml
之外,不需要额外的作业配置。然而,你必须更新你的 setup.py
,以确保它可以访问你的私有仓库。以下是一个示例配置:
-
更新
setup.py
,为每个在install_requires
列表中的依赖项创建一个dependency_links
属性,指向你的私有仓库:install_requires=['pyparsing>=2.0.3'], dependency_links=['https://pypi.example.com/simple/pyparsing'],
-
从你的仓库URL中获取证书,并将其添加到项目中:
printf "\n" | openssl s_client -connect pypi.example.com:443 -servername pypi.example.com | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > internal.crt
-
指向
setup.py
中的新下载的证书:import setuptools.ssl_support setuptools.ssl_support.cert_paths = ['internal.crt']
Python (Pipenv)
如果在网络连接性有限的环境中运行,你必须配置 PIPENV_PYPI_MIRROR
变量,以使用私有PyPi镜像。这个镜像必须包含默认和开发依赖项。
variables:
PIPENV_PYPI_MIRROR: https://pypi.example.com/simple
或者,如果不可能使用私有注册表,你可以将所需的包加载到Pipenv虚拟环境缓存中。对于这个选项,项目必须将 Pipfile.lock
检入到存储库中,并加载默认和开发包到缓存中。见python-pipenv
项目的示例,了解如何完成这项工作。
告警
我们建议您使用所有容器和所有包管理器及语言的最新支持版本。使用以前的版本会增加安全风险,因为不再支持的版本可能不再受益于活跃的安全报告和安全修复的回溯。
Gradle 项目
在为 Gradle 项目生成 HTML 依赖报告时,不要覆盖 reports.html.destination
或 reports.html.outputLocation
属性。这样做会导致依赖扫描无法正常工作。
Maven 项目
在隔离网络中,如果中央仓库是一个私有注册表(使用 <mirror>
指令明确设置),Maven 构建可能无法找到 gemnasium-maven-plugin
依赖项。这个问题的原因是 Maven 默认不会搜索本地仓库(/root/.m2
)并尝试从中央仓库获取。结果是一个关于缺少依赖项的错误。
解决方法
要解决这个问题,需要在你的 settings.xml
文件中添加一个 <pluginRepositories>
部分。这样可以让 Maven 在本地仓库中找到插件。
在开始之前,请考虑以下事项:
- 这个解决方法只适用于默认 Maven 中央仓库被镜像到私有注册表的环境。
- 应用这个解决方法后,Maven 会在本地仓库中搜索插件,这可能在某些环境中有安全风险。确保这符合你的组织的安全政策。
按照以下步骤修改
settings.xml
文件:
-
定位你的 Maven
settings.xml
文件。这个文件通常位于以下位置之一:-
/root/.m2/settings.xml
,用于根用户。 -
~/.m2/settings.xml
,用于普通用户。 -
${maven.home}/conf/settings.xml
,用于全局设置。
-
-
检查文件中是否已存在
<pluginRepositories>
部分。 -
如果已存在
<pluginRepositories>
部分,则只在其中添加以下<pluginRepository>
元素。否则,添加整个<pluginRepositories>
部分:<pluginRepositories> <pluginRepository> <id>local2</id> <name>本地仓库</name> <url>file:///root/.m2/repository/</url> </pluginRepository> </pluginRepositories>
-
再次运行你的 Maven 构建或依赖项扫描过程。
Python 项目
当使用 PIP_EXTRA_INDEX_URL
环境变量时,需要额外小心,因为漏洞 CVE-2018-20225:
版本号解析
在有些情况下,无法确定项目依赖项的版本是否处于安全公告所涉及的受影响范围内。
比如:
- 版本是未知的。
- 版本是有效的。
- 解析版本或将其和范围内进行对比时失败。
- 版本是一个分支,诸如
dev-master
或1.5.x
。 - 对比的版本是不确定的。比如,
1.0.0-20241502
无法和1.0.0-2
对比,因为一个版本包含时间戳,而另外一个未包含。
在这些情况下,分析器会跳过依赖并将消息输出到日志中。
极狐GitLab 分析器不会进行无端假设,因为这些假设可能会导致误报或漏报。
构建 Swift 项目
Swift 包管理器(SPM)是管理 Swift 代码发行版的官方工具。它和 Swift 构建系统进行了集成以自动化处理依赖的下载、便衣和链接。
当使用 SPM 构建 Swift 项目时,可遵循以下最佳实践。
-
包含一个
Package.resolved
文件。Package.resolved
文件会将依赖锁定到指定版本。总是将此文件条件到仓库中能够确保在不同环境下的一致性。git add Package.resolved git commit -m "Add Package.resolved to lock dependencies"
-
使用如下命令构建 Swift 项目:
# Update dependencies swift package update # Build the project swift build
-
要配置 CI/CD,将这些步骤添加到你的
.gitlab-ci.yml
文件中:swift-build: stage: build script: - swift package update - swift build
-
可选。如果你使用自签名的私有 Swift 软件包仓库,你可能需要将证书添加到你的项目中并配置 Swift 来信任它们:
-
获取证书:
echo | openssl s_client -servername your.repo.url -connect your.repo.url:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > repo-cert.crt
-
将下面内容调价到你的 Swift软件包清单中 (
Package.swift
):import Foundation #if canImport(Security) import Security #endif extension Package { public static func addCustomCertificate() { guard let certPath = Bundle.module.path(forResource: "repo-cert", ofType: "crt") else { fatalError("Certificate not found") } SecCertificateAddToSystemStore(SecCertificateCreateWithData(nil, try! Data(contentsOf: URL(fileURLWithPath: certPath)) as CFData)!) } } // Call this before defining your package Package.addCustomCertificate()
-
要总是在干净的环境下测试你的构建以确保你的依赖被正确指定而且能够被自动分析。
构建 CocoaPods 项目
CocoaPods 是一个针对 Swift 和 Objective-C Cocoa 项目的流行依赖管理器。它能够提供在 iOS、macOS、watchOS 和 tvOS 项目中管理外部库的标准格式。
当你使用 CocoaPods 来进行依赖管理并构建项目时,可遵循如下最佳实践。
-
包含一个
Podfile.lock
文件。Podfile.lock
文件对于你为指定版本锁定依赖来说非常重要。将此文件总是添加到你的仓库中来确保不同环境下的一致性。git add Podfile.lock git commit -m "Add Podfile.lock to lock CocoaPods dependencies"
-
你可以使用如下方式来构建你的项目:
-
xcodebuild
命令行工具:# Install CocoaPods dependencies pod install # Build the project xcodebuild -workspace YourWorkspace.xcworkspace -scheme YourScheme build
-
Xcode IDE:
- 在 Xcode 中打开你的
.xcworkspace
文件。 - 选择目标格式。
- 选择 产品 > 构建。你可以按 ⌘+B。
- 在 Xcode 中打开你的
-
fastlane,一个为 iOS 和 Android 应用程序构建和发布应用的自动化工具:
-
Install
fastlane
:sudo gem install fastlane
-
在你的项目中,配置
fastlane
:fastlane init
-
添加 lane 到
fastfile
:lane :build do cocoapods gym(scheme: "YourScheme") end
-
运行构建:
fastlane build
-
-
如果你的项目在同时使用 CocoaPods 和 Carthage,你可以使用 Carthage 来构建你的依赖:
- 创建一个包含你 CocoaPods 依赖的
Cartfile
文件。 -
运行如下命令:
carthage update --platform iOS
- 创建一个包含你 CocoaPods 依赖的
-
-
配置 CI/CD 来根据你偏爱的方法来构建项目。
比如,使用
xcodebuild
:cocoapods-build: stage: build script: - pod install - xcodebuild -workspace YourWorkspace.xcworkspace -scheme YourScheme build
-
可选。如果你使用私有的 CocoaPods 仓库,你可能需要配置你的项目来访问它们:
-
添加私有说明仓库:
pod repo add REPO_NAME SOURCE_URL
-
在你的 Podfile,指定源:
source 'https://github.com/CocoaPods/Specs.git' source 'SOURCE_URL'
-
-
可选。如果你的私有 CocoaPods 仓库使用 SSL,确保正确配置了 SSL 证书:
-
如果你使用自签名证书,将其添加到你系统的受信任证书中。你还可以在你的
.netrc
文件中指定 SSL 配置:machine your.private.repo.url login your_username password your_password
-
-
在你更新 Podfile 后,运行
pod install
t来安装并更新你的工作空间。
切记,在更新 Podfile 后总是要运行 pod install
以确保所有的依赖都被正确安装而且工作空间已被更新。