依赖扫描

极狐GitLab 提供的基于 Gemnasium 分析器的依赖扫描功能在极狐GitLab 17.9 中已被弃用,并在极狐GitLab 18.0 中停止支持。它被 使用 SBOM 的依赖扫描 和新的依赖扫描分析器所取代。

依赖扫描在您的应用程序的依赖项进入生产环境之前识别安全漏洞。此识别保护您的应用程序免受潜在的攻击和数据泄漏,这可能会损害用户信任和您的业务声誉。当在流水线运行期间发现漏洞时,它们会直接显示在您的合并请求中,让您在代码提交之前立即看到安全问题。

在流水线期间,您的代码中的所有依赖项,包括传递依赖项(嵌套依赖项),都会被自动分析。这种分析可以捕获人工审核过程中可能遗漏的安全问题。依赖扫描以最少的配置更改集成到您现有的 CI/CD 工作流中,使您从第一天起就能够实施安全的开发实践。

漏洞也可以在流水线之外通过 持续漏洞扫描 进行识别。

极狐GitLab 提供依赖扫描和 容器扫描 以确保覆盖所有这些依赖项类型。为了尽可能覆盖您的风险区域,我们鼓励您使用所有的安全扫描器。有关这些功能的比较,请参阅 依赖扫描与容器扫描比较

Dependency scanning Widget

依赖扫描不支持编译器和解释器的运行时安装。

支持的语言和软件包管理器#

以下语言和依赖管理器由依赖扫描支持:

语言语言版本软件包管理器支持的文件是否处理多个文件?
.NET所有版本NuGetpackages.lock.jsonY
C#
C所有版本Conanconan.lockY
C++
Go所有版本Go
  • go.mod
Y
Java 和 Kotlin 8 LTS, 11 LTS, 17 LTS, 或 21 LTS1 Gradle2
  • build.gradle
  • build.gradle.kts
N
Maven6pom.xmlN
JavaScript 和 TypeScript所有版本npm
  • package-lock.json
  • npm-shrinkwrap.json
Y
yarnyarn.lockY
pnpm3pnpm-lock.yamlY
PHP所有版本Composercomposer.lockY
Python3.117setuptools8setup.pyN
pip
  • requirements.txt
  • requirements.pip
  • requires.txt
N
Pipenv N
Poetry4poetry.lockN
uvuv.lockY
Ruby所有版本Bundler
  • Gemfile.lock
  • gems.locked
Y
Scala所有版本sbt5build.sbtN
Swift所有版本Swift 软件包管理器Package.resolvedN
Cocoapods9所有版本CocoaPodsPodfile.lockN
Dart10所有版本Pubpubspec.lockN
  1. Java 21 LTS 对于 sbt 仅限于版本 1.9.7。对于更多 sbt 版本的支持可以在 议题 430335 中追踪。 当 FIPS 模式 启用时,不支持。

  2. 当启用 FIPS 模式 时,不支持 Gradle。

  3. 支持 pnpm 锁文件是在 极狐GitLab 15.11 中引入的pnpm 锁文件不存储捆绑的依赖项,因此报告的依赖项可能与 npmyarn 不同。

  4. 支持具有 poetry.lock 文件的 Poetry 项目是在 极狐GitLab 15.0 中添加的。 支持没有 poetry.lock 文件的项目在议题中追踪: Poetry's pyproject.toml 支持依赖扫描。

  5. 对 sbt 1.0.x 的支持在极狐GitLab 16.8 中被弃用,并在极狐GitLab 17.0 中移除

  6. 对低于 3.8.8 的 Maven 的支持在极狐GitLab 16.9 中被弃用,并将在极狐GitLab 17.0 中移除。

  7. 对早期 Python 版本的支持在极狐GitLab 16.9 中被弃用,并在极狐GitLab 17.0 中移除

  8. 排除报告中的 pipsetuptools,因为安装程序需要它们。

  9. 只有 SBOM,没有建议。请参阅 关于 CocoaPods 建议研究的探索

  10. 尚无许可证检测。请参阅 关于 Dart 许可证检测的史诗

依赖检测#

依赖扫描自动检测代码库中使用的语言。匹配检测到的语言的所有分析器都会运行。通常不需要自定义分析器的选择。我们建议不要指定分析器,以便您自动使用完整选择以获得最佳覆盖,避免在出现弃用或移除时需要进行调整。然而,您可以使用变量 DS_EXCLUDED_ANALYZERS 覆盖选择。

语言检测依赖于 CI 作业 rules 来检测 支持的依赖文件

对于 Java 和 Python,当检测到支持的依赖文件时,依赖扫描尝试构建项目并执行一些 Java 或 Python 命令以获取依赖项列表。对于所有其他项目,锁定文件会被解析以获取依赖项列表,而无需首先构建项目。

所有直接和传递依赖项都会被分析,没有传递依赖项深度的限制。

分析器#

依赖扫描支持以下官方基于 Gemnasium 的分析器:

  • gemnasium
  • gemnasium-maven
  • gemnasium-python

这些分析器以 Docker 镜像的形式发布,依赖扫描使用它们为每次分析启动专用容器。您也可以集成一个自定义 安全扫描器

每个分析器在 Gemnasium 发布新版本时更新。有关更多信息,请参阅分析器 发布过程文档

分析器如何获取依赖信息#

极狐GitLab 分析器通过以下两种方法之一获取依赖信息:

  1. 直接解析锁定文件。
  2. 运行软件包管理器或构建工具生成依赖信息文件,然后进行解析。

通过解析锁定文件获取依赖信息#

以下软件包管理器使用极狐GitLab 分析器能够直接解析的锁定文件:

软件包管理器支持的文件格式版本测试的软件包管理器版本
Bundler不适用 1.17.3, 2.1.4
Composer不适用 1.x
Conan0.4 1.x
Go不适用 1.x
NuGetv1, v21 4.9
npmv1, v2, v32 6.x, 7.x, 9.x
pnpmv5, v6, v9 7.x, 8.x 9.x
yarn版本 1, 2, 3, 43 1.x, 2.x, 3.x
Poetryv1 1.x
uvv0.x 0.x
  1. 对 NuGet 版本 2 锁定文件的支持是在 极狐GitLab 16.2 中引入的

  2. lockfileVersion = 3 的支持是在 极狐GitLab 15.7 中引入的

  3. 对 Yarn 版本 4 的支持是在 极狐GitLab 16.11 中引入的

    以下功能对 Yarn Berry 不支持:

    包含补丁、工作区或两者的 Yarn 文件仍会被处理,但这些功能会被忽略。

通过运行软件包管理器生成可解析文件获取依赖信息#

为了支持以下软件包管理器,极狐GitLab 分析器分两步进行:

  1. 执行软件包管理器或特定任务以导出依赖信息。
  2. 解析导出的依赖信息。
软件包管理器预安装版本测试版本
sbt1.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
maven3.9.8 3.9.81
Gradle 6.7.12, 7.6.42, 8.82 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.153, 2023.11.15
Go 1.21 1.214
  1. 此测试使用 .tool-versions 文件中指定的 maven 默认版本。

  2. 不同版本的 Java 需要不同版本的 Gradle。上表中列出的 Gradle 版本已预安装在分析器镜像中。分析器使用的 Gradle 版本取决于您的项目是否使用 gradlew(Gradle 包装器)文件:

    • 如果您的项目不使用 gradlew 文件,则分析器会自动切换到预安装的 Gradle 版本之一,基于由 DS_JAVA_VERSION 变量指定的 Java 版本(默认版本为 17)。

      对于 Java 版本 811,Gradle 6.7.1 会被自动选择,Java 17 使用 Gradle 7.6.4,Java 21 使用 Gradle 8.8

    • 如果您的项目使用 gradlew 文件,则分析器镜像中预安装的 Gradle 版本会被忽略,使用您 gradlew 文件中指定的版本。

  3. 此测试确认如果找到了 Pipfile.lock 文件,它会被 Gemnasium 用来扫描此文件中列出的确切软件包版本。

  4. 由于 go build 的实现,Go 构建过程需要网络访问、通过 go mod download 预加载的 mod 缓存或已供应的依赖项。有关更多信息,请参阅 Go 文档关于编译软件包和依赖项

分析器如何触发#

极狐GitLab 依赖于 rules:exists 来启动相关分析器,通过代码库中支持文件的存在来检测语言,如 上表 所示。最多搜索从代码库根目录开始的两个目录级别。例如,如果代码库包含 Gemfileapi/Gemfileapi/client/Gemfile,则启用 gemnasium-dependency_scanning 作业,但如果唯一支持的依赖文件是 api/v1/client/Gemfile,则不会启用。

多个文件如何处理#

Python#

我们只在检测到要求文件或锁定文件的目录中执行一次安装。依赖项仅由 gemnasium-python 分析第一个检测到的文件。文件的搜索顺序如下:

  1. 对于使用 Pip 的项目,搜索 requirements.txtrequirements.piprequires.txt
  2. 对于使用 Pipenv 的项目,搜索 PipfilePipfile.lock
  3. 对于使用 Poetry 的项目,搜索 poetry.lock
  4. 对于使用 Setuptools 的项目,搜索 setup.py

搜索从根目录开始,如果在根目录中找不到构建,则继续搜索子目录。因此,根目录中的 Poetry 锁定文件会在子目录中的 Pipenv 文件之前被检测到。

Java 和 Scala#

我们只在检测到构建文件的目录中执行一次构建。对于包含多个 Gradle、Maven 或 sbt 构建或这些的任何组合的大型项目,gemnasium-maven 仅分析第一个检测到的构建文件的依赖项。构建文件的搜索顺序如下:

  1. 对于单个或多模块 Maven 项目,搜索 pom.xml
  2. 对于单个或多项目 Gradle 构建,搜索 build.gradlebuild.gradle.kts
  3. 对于单个或多项目 sbt 构建,搜索 build.sbt

搜索从根目录开始,如果在根目录中找不到构建,则继续搜索子目录。因此,根目录中的 sbt 构建文件会在子目录中的 Gradle 构建文件之前被检测到。对于多模块 Maven 项目,以及多项目Gradle 和 sbt 构建,如果在父构建文件中声明,则分析子模块和子项目文件。

JavaScript#

以下分析器会被执行,每个分析器在处理多个文件时具有不同行为:

  • Gemnasium

    支持多个锁定文件

  • Retire.js

    不支持多个锁定文件。当存在多个锁定文件时,Retire.js 会分析按字母顺序遍历目录树时发现的第一个锁定文件。

gemnasium 分析器扫描支持 JavaScript 项目的已供应库(即那些被检查到项目中但未由软件包管理器管理的库)。

Go#

支持多个文件。当检测到 go.mod 文件时,分析器尝试使用最小版本选择生成构建列表。如果失败,分析器会尝试解析 go.mod 文件中的依赖项。

作为要求,go.mod 文件应使用命令 go mod tidy 清理,以确保正确管理依赖项。此过程会对每个检测到的 go.mod 文件重复。

PHP、C、C++、.NET、C#、Ruby、JavaScript#

这些语言的分析器支持多个锁定文件。

其他语言的支持#

其他语言、依赖管理器和依赖文件的支持在以下议题中追踪:

软件包管理器语言支持的文件扫描工具
PoetryPythonpyproject.tomlGemnasium

配置#

启用依赖扫描分析器以确保扫描应用程序的依赖项以查找已知的漏洞。然后,您可以使用 CI/CD 变量调整其行为。

启用分析器#

先决条件:

  1. .gitlab-ci.yml 文件中需要 test 阶段。
  2. 使用私有化部署 runner 时,需要一个极狐GitLab Runner 和 dockerkubernetes 执行器。
  3. 如果您在 JihuLab.com 上使用 SaaS runner,这个是默认启用的。

要启用分析器,可以:

  1. 启用 自动 DevOps,其中包括依赖扫描。
  2. 使用预配置的合并请求。
  3. 创建一个执行政策的 扫描执行政策,以强制执行依赖扫描。
  4. 手动编辑 .gitlab-ci.yml 文件。
  5. 使用 CI/CD 组件

使用预配置的合并请求#

此方法会自动准备一个合并请求,其中包括 .gitlab-ci.yml 文件中的依赖扫描模板。然后合并合并请求以启用依赖扫描。

此方法最好在没有现有 .gitlab-ci.yml 文件或配置文件较少的情况下使用。如果您有复杂的极狐GitLab 配置文件,它可能无法成功解析,并可能发生错误。在这种情况下,请使用 手动 方法。

要启用依赖扫描:

  1. 在左侧边栏中,选择 搜索或转到,找到您的项目。
  2. 选择 安全 > 安全配置
  3. 依赖扫描 行中,选择 使用合并请求配置
  4. 选择 创建合并请求
  5. 审核合并请求,然后选择 合并

流水线现在包括一个依赖扫描作业。

手动编辑 .gitlab-ci.yml 文件#

此方法需要您手动编辑现有的 .gitlab-ci.yml 文件。如果您的极狐GitLab CI/CD 配置文件很复杂,请使用此方法。

要启用依赖扫描:

  1. 在左侧边栏中,选择 搜索或转到,找到您的项目。

  2. 选择 构建 > 流水线编辑器

  3. 如果不存在 .gitlab-ci.yml 文件,请选择 配置流水线,然后删除示例内容。

  4. 复制并粘贴以下内容到 .gitlab-ci.yml 文件的底部。如果已经存在 include 行,只需在其下面添加 template 行。

    yaml
    include: - template: Jobs/Dependency-Scanning.gitlab-ci.yml
  5. 选择 验证 标签,然后选择 验证流水线

    模拟成功完成 消息确认文件有效。

  6. 选择 编辑 标签。

  7. 完成字段。不要使用 分支 字段的默认分支。

  8. 选择 使用这些更改启动新的合并请求 复选框,然后选择 提交更改

  9. 根据标准工作流程完成字段,然后选择 创建合并请求

  10. 根据标准工作流程审查和编辑合并请求,然后选择 合并

流水线现在包括一个依赖扫描作业。

使用 CI/CD 组件#

History
    1. 在极狐GitLab 17.0 中引入。此功能是一个 实验
    2. 依赖扫描 CI/CD 组件仅支持 Android 项目。

使用 CI/CD 组件 执行应用程序的依赖扫描。有关说明,请参阅各自组件的 README 文件。

可用的 CI/CD 组件#

请参阅 https://gitlab.com/explore/catalog/components/dependency-scanning

在合并请求流水线中运行作业#

请参阅 使用合并请求流水线的安全扫描工具

自定义分析器行为#

要自定义依赖扫描,请使用 CI/CD 变量

在合并这些更改到默认分支之前,在合并请求中测试所有极狐GitLab 分析器的自定义设置。如果不这样做可能会导致意外结果,包括大量误报。

覆盖依赖扫描作业#

要覆盖作业定义(例如,更改 variablesdependencies 等属性),声明一个与要覆盖的作业同名的新作业。在模板包含后放置此新作业,并在其下指定任何其他键。例如,禁用 gemnasium 分析器的 DS_REMEDIATE

yaml
1include: 2 - template: Jobs/Dependency-Scanning.gitlab-ci.yml 3 4gemnasium-dependency_scanning: 5 variables: 6 DS_REMEDIATE: "false"

要覆盖 dependencies: [] 属性,请如上所述添加覆盖作业,针对该属性:

yaml
include: - template: Jobs/Dependency-Scanning.gitlab-ci.yml gemnasium-dependency_scanning: dependencies: ["build"]

可用的 CI/CD 变量#

您可以使用 CI/CD 变量 自定义 依赖扫描行为。

全局分析器设置#

以下变量允许配置全局依赖扫描设置。

CI/CD 变量描述
ADDITIONAL_CA_CERT_BUNDLE要信任的 CA 证书包。此处提供的证书包在扫描过程中也用于其他工具,例如 gityarnnpm。有关更多详情,请参阅 自定义 TLS 证书授权
DS_EXCLUDED_ANALYZERS指定要从依赖扫描中排除的分析器(按名称)。有关更多信息,请参阅 分析器
DS_EXCLUDED_PATHS根据路径排除要扫描的文件和目录。逗号分隔的模式列表。模式可以是 globs,也可以是文件或文件夹路径(例如,doc,spec)。父目录也匹配模式。这是一个在执行扫描之前应用的预过滤器。默认值:"spec, test, tests, tmp"
DS_IMAGE_SUFFIX添加到镜像名称的后缀。(极狐GitLab 团队成员可以在此机密议题中查看更多信息:https://gitlab.com/gitlab-org/gitlab/-/issues/354796)。在启用 FIPS 模式时自动设置为 "-fips"
DS_MAX_DEPTH定义分析器应搜索支持文件进行扫描的目录层级深度。值为 -1 时扫描所有目录,无论深度如何。默认值:2
SECURE_ANALYZERS_PREFIX覆盖提供官方默认镜像(代理)的 Docker 注册表名称。

特定分析器设置#

以下变量配置特定依赖扫描分析器的行为。

CI/CD 变量分析器默认值描述
GEMNASIUM_DB_LOCAL_PATHgemnasium/gemnasium-db本地 Gemnasium 数据库的路径。
GEMNASIUM_DB_UPDATE_DISABLEDgemnasium"false"禁用自动更新 gemnasium-db 顾问数据库。有关用法,请参阅 访问极狐GitLab 顾问数据库
GEMNASIUM_DB_REMOTE_URLgemnasiumhttps://gitlab.com/gitlab-org/security-products/gemnasium-db.git用于获取极狐GitLab 顾问数据库的仓库 URL。
GEMNASIUM_DB_REF_NAMEgemnasiummaster远程仓库数据库的分支名称。需要 GEMNASIUM_DB_REMOTE_URL
DS_REMEDIATEgemnasium"true",在 FIPS 模式下为 "false"启用自动修复易受攻击的依赖项。在 FIPS 模式下不支持。
DS_REMEDIATE_TIMEOUTgemnasium5m自动修复的超时。
GEMNASIUM_LIBRARY_SCAN_ENABLEDgemnasium"true"启用检测在 JavaScript 库(未由软件包管理器管理的库)中的漏洞。此功能要求在提交中存在 JavaScript 锁定文件,否则不会执行依赖扫描且不扫描库文件。
依赖扫描使用 Retire.js 扫描仪来检测有限的漏洞集。
DS_INCLUDE_DEV_DEPENDENCIESgemnasium"true"如果设置为 "false",则不会报告开发依赖项及其漏洞。仅支持使用 Composer、Maven、npm、pnpm、Pipenv 或 Poetry 的项目。在极狐GitLab 15.1 中引入。
GOOSgemnasium"linux"要编译 Go 代码的操作系统。
GOARCHgemnasium"amd64"要编译 Go 代码的处理器架构。
GOFLAGSgemnasium传递给 go build 工具的标志。
GOPRIVATEgemnasium要从源中获取的 glob 模式和前缀列表。
DS_JAVA_VERSIONgemnasium-maven17Java 的版本。可用版本:8111721
MAVEN_CLI_OPTSgemnasium-maven"-DskipTests --batch-mode"分析器传递给 maven 的命令行参数列表。
GRADLE_CLI_OPTSgemnasium-maven分析器传递给 gradle 的命令行参数列表。
GRADLE_PLUGIN_INIT_PATHgemnasium-maven"gemnasium-init.gradle"指定 Gradle 初始化脚本的路径。初始化脚本必须包括 allprojects { apply plugin: 'project-report' } 以确保兼容性。
DS_GRADLE_RESOLUTION_POLICYgemnasium-maven"failed"控制 Gradle 依赖解析的严格性。接受 "none" 允许部分结果,或 "failed" 在任何依赖项无法解析时失败扫描。
SBT_CLI_OPTSgemnasium-maven分析器传递给 sbt 的命令行参数列表。
PIP_INDEX_URLgemnasium-pythonhttps://pypi.org/simplePython 软件包索引的基本 URL。
PIP_EXTRA_INDEX_URLgemnasium-python额外软件包索引的额外 URL数组,除了 PIP_INDEX_URL。逗号分隔。警告: 使用此环境变量时,请阅读 以下安全注意事项
PIP_REQUIREMENTS_FILEgemnasium-python要扫描的 pip 需求文件。这是一个文件名而不是路径。设置此环境变量时,仅扫描指定的文件。
PIPENV_PYPI_MIRRORgemnasium-python如果设置,将使用镜像覆盖 Pipenv 使用的 PyPi 索引。
DS_PIP_VERSIONgemnasium-python强制安装特定的 pip 版本(例如:"19.3"),否则使用 Docker 镜像中安装的 pip。
DS_PIP_DEPENDENCY_PATHgemnasium-python加载 Python pip 依赖项的路径。

其他变量#

前面的表格不是所有可用变量的详尽列表。它们包含我们支持和测试的所有特定极狐GitLab 和分析器变量。还有许多变量,例如环境变量,可以传递并且确实有效。这个列表很大,我们可能不了解其中的许多,因此没有记录。

例如,要将非极狐GitLab 环境变量 HTTPS_PROXY 传递给所有依赖扫描作业,您可以像这样在 .gitlab-ci.yml 文件中将其设置为 CI/CD 变量

yaml
variables: HTTPS_PROXY: "https://squid-proxy:3128"

Gradle 项目需要设置 额外变量 来使用代理。

或者我们可以在特定作业中使用它,如依赖扫描:

yaml
dependency_scanning: variables: HTTPS_PROXY: $HTTPS_PROXY

由于我们没有测试所有变量,您可能会发现有些有效而有些无效。

自定义 TLS 证书授权#

依赖扫描允许使用自定义 TLS 证书进行 SSL/TLS 连接,而不是分析器容器镜像中默认提供的证书。

支持自定义证书授权是在以下版本中引入的。

分析器版本
gemnasiumv2.8.0
gemnasium-mavenv2.9.0
gemnasium-pythonv2.7.0

使用自定义 TLS 证书授权#

要使用自定义 TLS 证书授权,请将 X.509 PEM 公钥证书的文本表示分配给 CI/CD 变量 ADDITIONAL_CA_CERT_BUNDLE

例如,要在 .gitlab-ci.yml 文件中配置证书:

yaml
1variables: 2 ADDITIONAL_CA_CERT_BUNDLE: | 3 -----BEGIN CERTIFICATE----- 4 MIIGqTCCBJGgAwIBAgIQI7AVxxVwg2kch4d56XNdDjANBgkqhkiG9w0BAQsFADCB 5 ... 6 jWgmPqF3vUbZE0EyScetPJquRFRKIesyJuBFMAs= 7 -----END CERTIFICATE-----

使用私有 Maven 仓库进行身份验证#

要使用需要身份验证的私有 Maven 仓库,您应该将凭证存储在 CI/CD 变量中,并在 Maven 设置文件中引用它们。不要将凭证添加到 .gitlab-ci.yml 文件中。

要与私有 Maven 仓库进行身份验证:

  1. MAVEN_CLI_OPTS CI/CD 变量添加到您的 项目设置 中,并设置值以包含您的凭证。

    例如,如果您的用户名是 myuser,密码是 verysecret

    类型
    变量MAVEN_CLI_OPTS--settings mysettings.xml -Drepository.password=verysecret -Drepository.user=myuser
  2. 创建一个带有服务器配置的 Maven 设置文件。

    例如,将以下内容添加到设置文件 mysettings.xml 中。此文件在 MAVEN_CLI_OPTS CI/CD 变量中被引用。

    xml
    1<!-- mysettings.xml --> 2<settings> 3 ... 4 <servers> 5 <server> 6 <id>private_server</id> 7 <username>${repository.user}</username> 8 <password>${repository.password}</password> 9 </server> 10 </servers> 11</settings>

启用 FIPS 的镜像#

History
    1. 在极狐GitLab 15.0 中引入 - Gemnasium 在启用 FIPS 模式时使用启用 FIPS 的镜像。

极狐GitLab 还提供启用 FIPS 的 Red Hat UBI 版本的 Gemnasium 镜像。当极狐GitLab 实例中启用 FIPS 模式时,Gemnasium 扫描作业会自动使用启用 FIPS 的镜像。要手动切换到启用 FIPS 的镜像,请将变量 DS_IMAGE_SUFFIX 设置为 "-fips"

在 FIPS 模式下不支持 Gradle 项目的依赖扫描和 Yarn 项目的自动修复。

启用 FIPS 的镜像基于 RedHat 的 UBI 微镜像。它们没有软件包管理器,如 dnfmicrodnf,因此无法在运行时安装系统软件包。

输出#

依赖扫描产生以下输出:

  1. 依赖扫描报告:包含在依赖项中检测到的所有漏洞的详细信息。
  2. CycloneDX 软件材料清单:为每个支持的锁定或构建文件检测到的软件材料清单 (SBOM)。

依赖扫描报告#

依赖扫描输出包含所有漏洞详细信息的报告。报告在内部处理,结果显示在 UI 中。报告也作为依赖扫描作业的产物输出,命名为 gl-dependency-scanning-report.json

有关依赖扫描报告的更多详情,请参阅:

CycloneDX 软件材料清单#

History
    1. 在极狐GitLab 15.7 中 GA。

依赖扫描为每个支持的锁定或构建文件输出 CycloneDX 软件材料清单 (SBOM)。

CycloneDX SBOMs 是:

  1. 命名为 gl-sbom-<package-type>-<package-manager>.cdx.json
  2. 可作为依赖扫描作业的作业产物使用。
  3. 保存在检测到的锁定或构建文件的同一目录中。

例如,如果您的项目具有以下结构:

plaintext
1. 2├── ruby-project/ 3│ └── Gemfile.lock 4├── ruby-project-2/ 5│ └── Gemfile.lock 6├── php-project/ 7│ └── composer.lock 8└── go-project/ 9 └── go.sum

那么 Gemnasium 扫描仪生成以下 CycloneDX SBOMs:

plaintext
1. 2├── ruby-project/ 3│ ├── Gemfile.lock 4│ └── gl-sbom-gem-bundler.cdx.json 5├── ruby-project-2/ 6│ ├── Gemfile.lock 7│ └── gl-sbom-gem-bundler.cdx.json 8├── php-project/ 9│ ├── composer.lock 10│ └── gl-sbom-packagist-composer.cdx.json 11└── go-project/ 12 ├── go.sum 13 └── gl-sbom-go-go.cdx.json

合并多个 CycloneDX SBOMs#

您可以使用 CI/CD 作业将多个 CycloneDX SBOM 合并为一个 SBOM。极狐GitLab 使用 CycloneDX Properties 在每个 CycloneDX SBOM 的元数据中存储实现特定的详细信息,例如构建和锁定文件的位置。如果多个 CycloneDX SBOM 合并在一起,则这些信息会从生成的合并文件中删除。

例如,以下 .gitlab-ci.yml 提取演示了如何合并 Cyclone SBOM 文件,并验证生成的文件。

yaml
1stages: 2 - test 3 - merge-cyclonedx-sboms 4 5include: 6 - template: Jobs/Dependency-Scanning.gitlab-ci.yml 7 8merge cyclonedx sboms: 9 stage: merge-cyclonedx-sboms 10 image: 11 name: cyclonedx/cyclonedx-cli:0.25.1 12 entrypoint: [""] 13 script: 14 - find . -name "gl-sbom-*.cdx.json" -exec cyclonedx merge --output-file gl-sbom-all.cdx.json --input-files "{}" + 15 # optional: validate the merged sbom 16 - cyclonedx validate --input-version v1_4 --input-file gl-sbom-all.cdx.json 17 artifacts: 18 paths: 19 - gl-sbom-all.cdx.json

离线环境#

  1. 层级:旗舰版
  2. 提供:私有化部署

对于在访问外部资源受到限制、受限或间歇性访问的环境中的实例,依赖扫描作业需要进行一些调整才能成功运行。有关更多信息,请参阅 离线环境

要求#

要在离线环境中运行依赖扫描,您必须有:

  1. 一个具有 dockerkubernetes 执行器的极狐GitLab Runner
  2. 依赖扫描分析器镜像的本地副本

分析器镜像的本地副本#

要使用依赖扫描以及所有 支持的语言和框架

  1. 将以下默认依赖扫描分析器镜像从 registry.gitlab.com 导入到您的 本地 Docker 容器镜像仓库 中:

    plaintext
    1registry.gitlab.com/security-products/gemnasium:5 2registry.gitlab.com/security-products/gemnasium:5-fips 3registry.gitlab.com/security-products/gemnasium-maven:5 4registry.gitlab.com/security-products/gemnasium-maven:5-fips 5registry.gitlab.com/security-products/gemnasium-python:5 6registry.gitlab.com/security-products/gemnasium-python:5-fips

    将 Docker 镜像导入到本地离线 Docker 注册表的过程取决于 您的网络安全策略。请咨询 IT 人员以找到一个接受和批准的过程,通过该过程可以导入或暂时访问外部资源。这些扫描仪 定期更新,并且您可能需要定期下载它们。

  2. 配置极狐GitLab CI/CD 使用本地分析器。

    将 CI/CD 变量 SECURE_ANALYZERS_PREFIX 的值设置为您的本地 Docker 注册表 - 在此示例中为 docker-registry.example.com

    yaml
    include: - template: Jobs/Dependency-Scanning.gitlab-ci.yml variables: SECURE_ANALYZERS_PREFIX: "docker-registry.example.com/analyzers"

获取极狐GitLab Advisory 数据库#

GitLab Advisory 数据库是 gemnasiumgemnasium-mavengemnasium-python 分析器使用的漏洞数据来源。这些分析器的 Docker 镜像包含数据库的克隆副本。在开始扫描之前,克隆与数据库同步,以确保分析器拥有最新的漏洞数据。

在离线环境中,极狐GitLab Advisory 数据库的默认主机不可访问。相反,您必须将数据库托管在极狐GitLab runners 可访问的地方。您还必须按照自己的时间表手动更新数据库。

可用的托管数据库选项有:

使用极狐GitLab Advisory 数据库的克隆#

推荐使用极狐GitLab Advisory 数据库的克隆,因为它是最有效的方法。

要托管极狐GitLab Advisory 数据库的克隆:

  1. 将极狐GitLab Advisory 数据库克隆到一个极狐GitLab runners 可以通过 HTTP 访问的主机。
  2. 在您的 .gitlab-ci.yml 文件中,设置 CI/CD 变量 GEMNASIUM_DB_REMOTE_URL 的值为 Git 仓库的 URL。

例如:

yaml
variables: GEMNASIUM_DB_REMOTE_URL: https://users-own-copy.example.com/gemnasium-db.git

使用极狐GitLab Advisory 数据库的副本#

使用极狐GitLab Advisory 数据库的副本需要您托管一个由分析器下载的归档文件。

要使用极狐GitLab Advisory 数据库的副本:

  1. 将极狐GitLab Advisory 数据库的归档下载到一个极狐GitLab runners 可以通过 HTTP 访问的主机。归档位于 https://gitlab.com/gitlab-org/security-products/gemnasium-db/-/archive/master/gemnasium-db-master.tar.gz

  2. 更新您的 .gitlab-ci.yml 文件。

    • 设置 CI/CD 变量 GEMNASIUM_DB_LOCAL_PATH 使用数据库的本地副本。
    • 设置 CI/CD 变量 GEMNASIUM_DB_UPDATE_DISABLED 禁用数据库更新。
    • 在扫描开始之前下载并提取 advisory 数据库。
    yaml
    1variables: 2 GEMNASIUM_DB_LOCAL_PATH: ./gemnasium-db-local 3 GEMNASIUM_DB_UPDATE_DISABLED: "true" 4 5dependency_scanning: 6 before_script: 7 - wget https://local.example.com/gemnasium_db.tar.gz 8 - mkdir -p $GEMNASIUM_DB_LOCAL_PATH 9 - tar -xzvf gemnasium_db.tar.gz --strip-components=1 -C $GEMNASIUM_DB_LOCAL_PATH

使用代理与 Gradle 项目#

Gradle wrapper 脚本不读取 HTTP(S)_PROXY 环境变量。

要使 Gradle wrapper 脚本使用代理,您可以使用 GRADLE_CLI_OPTS CI/CD 变量指定选项:

yaml
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_CLI_OPTS CI/CD 变量指示 Maven 使用此配置:

yaml
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,以确保它能够访问您的私有仓库。以下是示例配置:

  1. 更新 setup.py 创建一个 dependency_links 属性,为 install_requires 列表中的每个依赖指向您的私有仓库:

    python
    install_requires=['pyparsing>=2.0.3'], dependency_links=['https://pypi.example.com/simple/pyparsing'],
  2. 从您的仓库 URL 获取证书并将其添加到项目中:

    shell
    printf "\n" | openssl s_client -connect pypi.example.com:443 -servername pypi.example.com | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > internal.crt
  3. 指向 setup.py 到新下载的证书:

    python
    import setuptools.ssl_support setuptools.ssl_support.cert_paths = ['internal.crt']

Python (Pipenv)#

如果在有限的网络连接环境中运行,您必须配置 PIPENV_PYPI_MIRROR 变量以使用私有 PyPi 镜像。此镜像必须包含默认和开发依赖项。

yaml
variables: PIPENV_PYPI_MIRROR: https://pypi.example.com/simple

或者,如果无法使用私有注册表,您可以将所需的软件包加载到 Pipenv 虚拟环境缓存中。对于此选项,项目必须将 Pipfile.lock 检入仓库,并将默认和开发软件包都加载到缓存中。

警告#

我们建议您使用所有容器的最新版本,以及所有软件包管理器和语言的最新支持版本。使用旧版本会增加安全风险,因为不支持的版本可能不再享受主动的安全报告和安全修复的回溯移植。

Gradle 项目#

在为 Gradle 项目生成 HTML 依赖报告时,不要覆盖 reports.html.destinationreports.html.outputLocation 属性。这样做会阻止依赖扫描正常工作。

Maven 项目#

在隔离网络中,如果中央仓库是私有注册表(使用 <mirror> 指令显式设置),Maven 构建可能无法找到 gemnasium-maven-plugin 依赖项。此问题发生是因为 Maven 默认不搜索本地仓库 (/root/.m2),而尝试从中央仓库获取。结果是关于缺少依赖项的错误。

解决方法#

要解决这个问题,请在你的 settings.xml 文件中添加一个 <pluginRepositories> 部分。这允许 Maven 在本地库中找到插件。

在开始之前,请考虑以下事项:

  • 此解决方法仅适用于默认的 Maven 中央库被镜像到私有注册表的环境。
  • 应用此解决方法后,Maven 会在本地库中搜索插件,这在某些环境中可能会有安全隐患。确保这符合你组织的安全策略。

按照以下步骤修改 settings.xml 文件:

  1. 找到你的 Maven settings.xml 文件。此文件通常位于以下位置之一:

    • /root/.m2/settings.xml 对于 root 用户。
    • ~/.m2/settings.xml 对于普通用户。
    • ${maven.home}/conf/settings.xml 全局设置。
  2. 检查文件中是否存在 <pluginRepositories> 部分。

  3. 如果 <pluginRepositories> 部分已经存在,只需在其中添加以下 <pluginRepository> 元素。否则,添加整个 <pluginRepositories> 部分:

    xml
    1 <pluginRepositories> 2 <pluginRepository> 3 <id>local2</id> 4 <name>local repository</name> 5 <url>file:///root/.m2/repository/</url> 6 </pluginRepository> 7 </pluginRepositories>
  4. 重新运行你的 Maven 构建或依赖扫描过程。

#

Python 项目#

由于 PIP_EXTRA_INDEX_URL 环境变量可能存在的漏洞(由 CVE-2018-20225 记录),使用时需要特别注意:

在 pip(所有版本)中发现了一个议题,因为它安装了版本号最高的版本,即使用户本意是从私有索引获取私有软件包。这仅影响使用 PIP_EXTRA_INDEX_URL 选项,并且利用要求软件包不存在于公共索引中(因此攻击者可以在那里放置具有任意版本号的软件包)。

#

版本号解析#

在某些情况下,无法确定项目依赖的版本是否在安全公告的影响范围内。

例如:

  • 版本未知。
  • 版本无效。
  • 解析版本或将其与范围比较失败。
  • 版本是一个分支,如 dev-master1.5.x
  • 比较的版本不明确。例如,1.0.0-20241502 无法与 1.0.0-2 比较,因为一个版本包含时间戳而另一个没有。

在这些情况下,分析器跳过依赖项并将消息输出到日志中。

极狐GitLab 分析器不做假设,因为这可能导致误报或漏报。

#

构建 Swift 项目#

Swift Package Manager (SPM) 是管理 Swift 代码分发的官方工具。它与 Swift 构建系统集成,以自动化下载、编译和链接依赖项的过程。

在使用 SPM 构建 Swift 项目时,请遵循以下最佳实践。

  1. 包含一个 Package.resolved 文件。

    Package.resolved 文件锁定你的依赖项到特定版本。始终将此文件提交到你的代码库中,以确保在不同环境中的一致性。

    shell
    git add Package.resolved git commit -m "Add Package.resolved to lock dependencies"
  2. 要构建你的 Swift 项目,请使用以下命令:

    shell
    # 更新依赖项 swift package update # 构建项目 swift build
  3. 要配置 CI/CD,请将这些步骤添加到你的 .gitlab-ci.yml 文件中:

    yaml
    swift-build: stage: build script: - swift package update - swift build
  4. 可选。如果你使用带有自签名证书的私有 Swift 软件包库,你可能需要将证书添加到你的项目并配置 Swift 信任它:

    1. 获取证书:

      shell
      echo | openssl s_client -servername your.repo.url -connect your.repo.url:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > repo-cert.crt
    2. 将这些行添加到你的 Swift 软件包清单 (Package.swift) 中:

      swift
      1import Foundation 2 3#if canImport(Security) 4import Security 5#endif 6 7extension Package { 8 public static func addCustomCertificate() { 9 guard let certPath = Bundle.module.path(forResource: "repo-cert", ofType: "crt") else { 10 fatalError("Certificate not found") 11 } 12 SecCertificateAddToSystemStore(SecCertificateCreateWithData(nil, try! Data(contentsOf: URL(fileURLWithPath: certPath)) as CFData)!) 13 } 14} 15 16// 在定义你的软件包之前调用此方法 17Package.addCustomCertificate()

始终在干净环境中测试你的构建过程,以确保你的依赖项被正确指定并自动解决。

#

构建 CocoaPods 项目#

CocoaPods 是一个流行的 Swift 和 Objective-C Cocoa 项目的依赖管理工具。它为 iOS、macOS、watchOS 和 tvOS 项目中的外部库管理提供了标准格式。

在使用 CocoaPods 构建项目时,请遵循以下最佳实践。

  1. 包含一个 Podfile.lock 文件。

    Podfile.lock 文件对于锁定你的依赖项到特定版本至关重要。始终将此文件提交到你的代码库中,以确保在不同环境中的一致性。

    shell
    git add Podfile.lock git commit -m "Add Podfile.lock to lock CocoaPods dependencies"
  2. 你可以使用以下之一构建你的项目:

    • xcodebuild 命令行工具:

      shell
      # 安装 CocoaPods 依赖项 pod install # 构建项目 xcodebuild -workspace YourWorkspace.xcworkspace -scheme YourScheme build
    • Xcode IDE:

      1. 在 Xcode 中打开你的 .xcworkspace 文件。
      2. 选择你的目标方案。
      3. 选择 产品 > 构建。你也可以按 +B
    • fastlane,一个用于自动化 iOS 和 Android 应用构建和发布的工具:

      1. 安装 fastlane

        shell
        sudo gem install fastlane
      2. 在你的项目中配置 fastlane

        shell
        fastlane init
      3. 在你的 fastfile 中添加一个 lane:

        ruby
        lane :build do cocoapods gym(scheme: "YourScheme") end
      4. 运行构建:

        shell
        fastlane build
    • 如果你的项目使用了 CocoaPods 和 Carthage,你可以使用 Carthage 构建你的依赖项:

      1. 创建一个 Cartfile,其中包含你的 CocoaPods 依赖项。

      2. 运行以下命令:

        shell
        carthage update --platform iOS
  3. 根据你的首选方法配置 CI/CD 以构建项目。

    例如,使用 xcodebuild

    yaml
    cocoapods-build: stage: build script: - pod install - xcodebuild -workspace YourWorkspace.xcworkspace -scheme YourScheme build
  4. 可选。如果你使用私有 CocoaPods 库,你可能需要配置你的项目以访问它们:

    1. 添加私有 spec 库:

      shell
      pod repo add REPO_NAME SOURCE_URL
    2. 在你的 Podfile 中指定源:

      ruby
      source 'https://github.com/CocoaPods/Specs.git' source 'SOURCE_URL'
  5. 可选。如果你的私有 CocoaPods 库使用 SSL,确保 SSL 证书已正确配置:

    • 如果你使用自签名证书,请将其添加到系统的受信任证书中。你也可以在 .netrc 文件中指定 SSL 配置:

      netrc
      machine your.private.repo.url login your_username password your_password
  6. 更新 Podfile 后,运行 pod install 以安装依赖项并更新工作空间。

请记住,在更新 Podfile 后始终运行 pod install,以确保所有依赖项已正确安装并且工作空间已更新。