什么是 ‘Software Bill of Materials (SBOM)’:在 Go 项目构建流程中自动审计第三方依赖的安全风险

尊敬的各位技术同行,

欢迎来到本次关于“Software Bill of Materials (SBOM)”的讲座。在当今复杂的软件生态系统中,第三方依赖无处不在,它们极大地加速了开发进程,但也带来了前所未有的安全挑战。软件供应链攻击的威胁日益严峻,从 SolarWinds 事件到 Log4j 漏洞,都深刻提醒我们,仅仅关注自身代码的安全已远远不够。我们需要一种机制,能够清晰地了解我们软件中的每一个“零件”,并据此自动化地审计其潜在的安全风险。这正是 Software Bill of Materials (SBOM) 诞生的核心价值。

今天,我们将深入探讨 SBOM 的概念、其重要性、核心标准,并重点聚焦如何在 Go 项目的构建流程中,利用自动化工具生成 SBOM,并进而审计第三方依赖的安全风险。我们将通过大量的代码示例,一步步演示如何将这一关键实践融入您的开发与部署流程,从而显著提升您的软件供应链安全性。

I. 软件供应链安全的基石

软件开发不再是孤立的活动。现代应用程序通常由数千个组件构成,其中大部分来自开源项目、第三方库、框架,甚至是操作系统和容器基础镜像。这种高度依赖的生态系统,虽然带来了效率和创新,却也为攻击者提供了新的切入点——软件供应链。

A. 软件供应链攻击的崛起

软件供应链攻击的目标不再是最终产品本身,而是其生产、交付或更新过程中的任何环节。攻击者可能通过以下方式渗透:

  • 篡改开源组件:向常用库中植入恶意代码。
  • 窃取代码签名密钥:对恶意软件进行合法签名。
  • 利用构建系统漏洞:在编译或打包过程中注入恶意内容。
  • 破坏分发渠道:在软件交付给用户前进行修改。

一旦供应链中的某个环节被攻破,其影响将波及所有使用受影响组件或流程的下游产品。这种“一传十,十传百”的扩散效应,使得软件供应链安全成为当前网络安全领域最紧迫的议题之一。

B. SBOM 的诞生背景与核心价值

面对日益严峻的软件供应链威胁,企业、政府和行业组织都在寻求更有效的防御策略。SBOM 正是在这种背景下应运而生的一种基础性工具。

SBOM,即软件物料清单 (Software Bill of Materials),顾名思义,它就像制造业中的产品物料清单一样,提供了一个关于软件产品中包含的所有组件的完整、准确、机器可读的列表。这个列表不仅仅是直接依赖,还应尽可能地包含所有间接(传递性)依赖,甚至包括操作系统组件、编译器、构建工具等。

SBOM 的核心价值在于:

  1. 提高透明度:让软件供应商和消费者都能清晰地了解软件的构成。
  2. 加速漏洞响应:当新的漏洞(如 Log4j 漏洞)被披露时,能够迅速识别哪些产品受到了影响,并采取行动。
  3. 满足合规性要求:越来越多的法规和标准(例如美国总统行政命令 EO 14028)要求软件供应商提供 SBOM。

C. 本讲座目标

本次讲座旨在:

  • 深入理解 SBOM 的概念、组成要素及重要性。
  • 掌握主流 SBOM 标准(SPDX、CycloneDX)。
  • 学习如何在 Go 项目中自动化生成高质量的 SBOM。
  • 利用 SBOM 结合自动化工具,审计第三方依赖的安全漏洞。
  • 将 SBOM 生成与审计流程无缝集成到 CI/CD 流水线中。
  • 探讨 SBOM 的最佳实践与未来发展趋势。

通过本次讲座,我希望您能够将 SBOM 视为软件开发生命周期中的一个不可或缺的环节,从而构建更安全、更可信赖的 Go 应用程序。

II. 什么是软件物料清单 (SBOM)?

SBOM 是对软件组件及其之间关系的正式的、机器可读的清单。它提供了软件构成元素的“DNA”图谱,使您能够追踪和管理这些组件。

A. SBOM 的定义与组成要素

一个完整的 SBOM 通常包含以下关键信息:

  1. 组件名称 (Component Name):库、模块或包的名称。例如:github.com/gin-gonic/gin
  2. 组件版本 (Component Version):组件的特定版本标识。例如:v1.7.7
  3. 供应商 (Supplier):提供该组件的实体。例如:Gin-GonicGoogle
  4. 唯一标识符 (Unique Identifier)
    • PURL (Package URL):一种通用的 URL 方案,用于唯一标识和定位软件包。例如:pkg:golang/github.com/gin-gonic/[email protected]
    • CPE (Common Platform Enumeration):一种结构化的命名方案,用于识别 IT 系统、平台和软件包。
    • SWID (Software Identification Tag):用于识别已安装软件的标签。
  5. 许可证信息 (License Information):组件使用的许可证类型。例如:MIT, Apache-2.0, GPL-3.0。这虽然不是直接的安全信息,但对合规性至关重要,且有时许可证的变更也可能引入新的风险。
  6. 依赖关系 (Dependency Relationships):组件之间的父子关系、同级关系等。例如:A 依赖 B,B 依赖 C。这是理解传递性依赖的关键。
  7. 哈希值 (Cryptographic Hashes):组件文件的哈希值(如 SHA-256),用于验证组件的完整性,确保其在传输过程中未被篡改。

表 1: SBOM 核心要素示例

要素 描述 示例
组件名称 软件库、模块或包的名称 github.com/gin-gonic/gin
组件版本 组件的特定版本 v1.7.7
供应商 提供组件的实体或组织 Gin-Gonic
唯一标识符 (PURL) 通用软件包定位符 pkg:golang/github.com/gin-gonic/[email protected]
许可证 组件使用的开源许可证 MIT
哈希值 (SHA256) 组件内容的加密哈希值 a1b2c3d4e5f67890...
依赖关系 指明组件依赖于其他哪些组件 myapp -> gin-gonic/gin, gin-gonic/gin -> go-playground/validator

B. SBOM 的重要性:为什么我们需要它?

SBOM 不仅仅是一个列表,它是构建软件供应链信任和安全的基础。

  1. 透明度与可追溯性

    • 对供应商而言:更全面地了解其产品的构成,更好地管理风险。
    • 对消费者而言:在部署软件前,可以审查其中包含的组件,评估其潜在风险,并做出明智的决策。
    • 当供应链发生安全事件时,SBOM 能够提供快速追踪和溯源的能力。
  2. 漏洞管理与响应

    • 当新的零日漏洞或高危漏洞(如 CVE-2021-44228,即 Log4j 漏洞)被公开时,组织可以利用 SBOM 快速识别其所有产品、服务或内部系统是否使用了受影响的组件及其版本。
    • 这大大缩短了从漏洞披露到风险评估再到打补丁的响应时间,将数周甚至数月的工作缩短到数小时或数天。
    • 没有 SBOM,您可能需要耗费大量人力,手动检查每一个应用程序的依赖,这在大型组织中几乎是不可能完成的任务。
  3. 合规性要求

    • 全球范围内,政府和行业监管机构对软件安全的关注日益增加。例如,美国总统在 2021 年发布的《改善国家网络安全行政命令》(Executive Order 14028) 中,明确要求向美国政府销售软件的供应商必须提供 SBOM。
    • 类似的合规性要求预计将在更多行业和地区推广,使得 SBOM 成为进入某些市场或与特定客户合作的必备条件。
  4. 许可证合规性 (次要但相关)

    • 虽然本次讲座主要聚焦安全风险,但 SBOM 中包含的许可证信息对于确保软件的合法使用和分发也至关重要。
    • 它可以帮助组织避免因违反开源许可证条款而带来的法律风险。

C. SBOM 的价值体现:从开发到运营

SBOM 的价值贯穿整个软件开发生命周期 (SDLC):

  • 开发阶段:开发人员可以在早期阶段识别并修复存在漏洞的依赖,避免将问题带入后期。
  • 构建阶段:自动化工具可以在构建时生成 SBOM,确保其与实际构建内容一致。
  • 测试阶段:安全团队可以利用 SBOM 进行更全面的渗透测试和安全评估。
  • 部署阶段:运维团队可以使用 SBOM 监控已部署软件的漏洞状态,并及时响应。
  • 运营与维护阶段:持续的漏洞扫描和 SBOM 更新,确保软件在整个生命周期内的安全性。

III. 核心 SBOM 标准与格式

为了实现 SBOM 的互操作性和自动化处理,行业内已经建立了几个核心标准。了解这些标准对于选择合适的工具和集成策略至关重要。

A. SPDX (Software Package Data Exchange)

SPDX 是由 Linux Foundation 发起和维护的一个开放标准,旨在为软件组件、许可证和安全信息提供一种通用的格式。它历史悠久,功能全面,能够描述非常详细的软件信息。

  1. 历史与特点

    • SPDX 的目标是解决软件供应链中透明度不足的问题。
    • 它提供了一种表达软件组件、依赖关系、许可证、版权、安全信息(如 CVE)以及其他元数据的标准化方式。
    • SPDX 支持多种序列化格式,包括 Tag-Value (文本)、RDF/XML、JSON 和 YAML。
  2. 数据模型概览

    • SPDX 文档 (SPDX Document):SBOM 的顶层容器。
    • 软件包 (Package):代表软件中的一个可分发组件。
    • 文件 (File):软件包中的单个文件,可以包含许可证、哈希等信息。
    • 片段 (Snippet):代码片段,用于描述从其他文件中提取的代码块。
    • 许可证 (License):明确组件的许可证。
    • 关系 (Relationship):描述软件包、文件等实体之间的关系,如 DEPENDS_ON, CONTAINS, GENERATED_FROM 等。
  3. SPDX 文档结构
    一个典型的 SPDX JSON 文档会包含以下顶级字段:

    • SPDXID:文档的唯一标识符。
    • spdxVersion:SPDX 规范的版本。
    • dataLicense:SPDX 文档内容的许可证(通常是 CC0-1.0)。
    • documentNamespace:文档的唯一 URI。
    • creationInfo:文档创建信息,包括创建者、日期等。
    • packages:包含所有软件包的数组,每个软件包有其名称、版本、许可证、哈希等。
    • files:包含所有文件的数组(如果需要详细到文件级别)。
    • relationships:描述组件之间关系的数组。
    • hasExtractedLicensingInfo:额外的许可证信息。

B. CycloneDX

CycloneDX 是由 OWASP (Open Web Application Security Project) 发起的一个轻量级、安全为中心的 SBOM 标准。它特别强调在自动化工具和 CI/CD 流程中的易用性。

  1. 历史与特点

    • CycloneDX 专注于软件供应链可见性和漏洞管理。
    • 它的设计目标是尽可能地简洁,便于机器解析和生成,使其非常适合自动化流程。
    • 支持 JSON 和 XML 两种序列化格式。
    • 在描述容器镜像、固件等非传统软件组件方面也表现出色。
  2. 轻量级与自动化友好

    • CycloneDX 的数据模型相对 SPDCX 更精简,主要关注组件、其版本、哈希、许可证以及最重要的是组件之间的依赖关系。
    • 这使得它在生成和解析时效率更高,更适合作为 CI/CD 管道中的快速 SBOM 生成步骤。
  3. 数据模型概览
    一个典型的 CycloneDX JSON 文档会包含以下顶级字段:

    • bomFormat:总是 CycloneDX
    • specVersion:CycloneDX 规范的版本。
    • serialNumber:BOM 的唯一标识符。
    • version:BOM 文档的版本。
    • metadata:描述 BOM 本身的元数据,如工具信息、时间戳等。
    • components:一个数组,包含所有组件的信息,每个组件有 name, version, purl, hashes, licenses 等。
    • dependencies:一个数组,描述组件之间的依赖关系,通常以 PURL 或组件的内部 uuid 作为引用。

C. SWID (Software Identification Tag) (简要提及)

SWID 标签是由 NIST (美国国家标准与技术研究院) 开发的 ISO/IEC 19770-2 标准,主要用于识别已安装的软件产品。它更多地关注软件的安装状态和生命周期管理,而不是像 SPDX 和 CycloneDX 那样提供全面的供应链信息。在 SBOM 语境中,SWID 标签可以作为组件的唯一标识符之一,但它本身不是一个完整的 SBOM 格式。

D. 标准比较与选择

特性 SPDX CycloneDX
发起组织 Linux Foundation OWASP
主要目标 综合的软件供应链透明度,包括许可证、版权、安全 安全为中心,自动化漏洞管理与供应链可见性
复杂性 较高,数据模型更详尽 较低,更轻量级,易于自动化
序列化格式 Tag-Value, RDF/XML, JSON, YAML JSON, XML
用例场景 许可证合规性、详细的供应链审计、长期归档 CI/CD 集成、快速漏洞扫描、容器 SBOM
组件描述 可细致到文件和代码片段 通常到软件包级别

选择建议

  • 如果您需要非常详细的许可证、版权和文件级信息,或者需要与法律团队紧密合作,SPDX 可能是更好的选择。
  • 如果您的主要目标是自动化漏洞管理,快速集成到 CI/CD 流程,并注重效率,那么 CycloneDX 通常是更受欢迎的选择。
  • 许多工具(如 syft)可以同时生成这两种格式的 SBOM,因此您也可以根据下游系统的需求来选择输出格式。在本讲座中,我们将主要演示如何生成这两种主流格式。

IV. Go 项目中的 SBOM 生成:自动化实践

在 Go 项目中生成 SBOM,其核心挑战在于如何准确地识别所有的直接和间接依赖。Go Modules 机制为我们提供了便利,但依然需要专门的工具来解析这些信息并将其转换为标准化的 SBOM 格式。

A. Go 模块与依赖管理回顾

Go 1.11 引入的 Go Modules 极大地改进了 Go 语言的依赖管理。

  • go.mod:定义了模块的路径、Go 版本以及直接依赖及其版本。
  • go.sum:包含了所有直接和间接依赖的加密哈希值,用于确保依赖的完整性和安全性。
  • 间接依赖 (Transitive Dependencies):当您的项目依赖的库又依赖了其他库时,这些就是间接依赖。SBOM 必须包含这些间接依赖,因为它们同样可能引入安全漏洞。

Go Modules 机制虽然提供了依赖信息,但它本身并未输出为标准化的 SBOM 格式。这就是为什么我们需要自动化工具。

B. 自动化工具 syft 深度解析

syft 是 Anchore 公司开发的一款强大的、开源的、语言无关的 SBOM 生成工具。它能够扫描文件系统、容器镜像、Git 仓库等,并自动检测其中的软件包、库和依赖关系,然后将其输出为 SPDX、CycloneDX 等多种标准格式的 SBOM。

  1. syft 的工作原理
    syft 通过多种扫描器来检测不同类型的软件包和依赖:

    • 文件系统扫描:遍历指定目录,查找常见的包管理文件(如 go.mod, package.json, pom.xml, requirements.txt 等)。
    • Go Modules 扫描器:专门解析 go.modgo.sum 文件,识别 Go 模块及其依赖。
    • 二进制文件扫描器:可以分析编译后的二进制文件,尝试识别嵌入的库信息(虽然对 Go 静态链接的二进制文件效果有限,但对其他语言可能有用)。
    • 容器镜像扫描:可以解压容器镜像层,扫描其中的文件系统。
  2. 安装与基本使用
    syft 的安装非常简单,支持多种操作系统。

    安装 syft (Linux/macOS):

    # 使用 Homebrew (macOS/Linux)
    brew install syft
    
    # 或者使用 Go 安装 (可能需要手动配置PATH)
    go install github.com/anchore/syft/cmd/syft@latest
    
    # 或者从 GitHub Release 下载二进制文件并添加到 PATH
    # 访问 https://github.com/anchore/syft/releases 下载适合您系统的版本

    验证安装:

    syft version
    # 例如输出: syft v0.98.0

    为了演示,我们先创建一个简单的 Go 项目:
    my-go-app/main.go:

    package main
    
    import (
        "fmt"
        "log"
        "net/http"
    
        "github.com/gin-gonic/gin"
        "github.com/spf13/viper" // 添加一个配置库作为依赖
    )
    
    func main() {
        // 初始化 Gin 框架
        r := gin.Default()
    
        // 示例路由
        r.GET("/ping", func(c *gin.Context) {
            c.JSON(http.StatusOK, gin.H{
                "message": "pong",
            })
        })
    
        // 使用 viper 读取配置 (只是为了引入依赖)
        viper.SetConfigName("config") // config.json, config.yaml, etc.
        viper.AddConfigPath(".")
        err := viper.ReadInConfig()
        if err != nil {
            log.Printf("Error reading config file: %s", err)
        } else {
            log.Printf("Config loaded: %v", viper.AllSettings())
        }
    
        fmt.Println("Server is running on :8080")
        // 启动 HTTP 服务器
        if err := r.Run(":8080"); err != nil {
            log.Fatalf("Failed to run server: %v", err)
        }
    }

    初始化 Go 模块并下载依赖:

    mkdir my-go-app
    cd my-go-app
    go mod init my-go-app
    go mod tidy
    # 这将生成 go.mod 和 go.sum 文件,并下载 gin 和 viper 及其间接依赖

    现在,我们可以使用 syft 来扫描这个 Go 项目。

    示例:扫描一个简单的 Go 项目

    # 在 my-go-app 目录下执行
    syft dir .

    输出会是一个纯文本的组件列表,包含名称、版本、类型等信息。这对于快速查看很有用,但不是标准的 SBOM 格式。

  3. 生成不同格式的 SBOM
    syft 最强大的功能是能够输出多种标准 SBOM 格式。

    生成 SPDX JSON 格式的 SBOM:

    syft dir . -o spdx-json > my-go-app-spdx.json

    my-go-app-spdx.json 文件将包含详细的 SPDX 格式 SBOM。您可以打开文件查看其结构。它会列出 my-go-app 及其所有的 Go 模块依赖,包括 gin, viper 以及它们各自的间接依赖。

    生成 CycloneDX JSON 格式的 SBOM:

    syft dir . -o cyclonedx-json > my-go-app-cyclonedx.json

    my-go-app-cyclonedx.json 文件将包含 CycloneDX 格式的 SBOM,通常比 SPDX 更简洁,但包含了所有核心信息。

    生成 GitHub Dependency Graph 格式的 SBOM:
    GitHub Dependency Graph 是 GitHub 用于其依赖图和 Dependabot 警报的基础。syft 也可以生成这种格式,便于集成到 GitHub 的安全功能中。

    syft dir . -o github > my-go-app-github.json

    表 2: syft 常用输出格式

    格式名称 描述 命令行选项
    Text 纯文本列表,适合快速查看 text (默认)
    SPDX JSON SPDX 2.X 标准,JSON 格式 spdx-json
    SPDX Tag-Value SPDX 2.X 标准,Tag-Value 文本格式 spdx-tag-value
    CycloneDX JSON CycloneDX 1.X 标准,JSON 格式 cyclonedx-json
    CycloneDX XML CycloneDX 1.X 标准,XML 格式 cyclonedx-xml
    GitHub JSON GitHub Dependency Graph 格式 github
    Syft JSON syft 工具的内部 JSON 格式,包含更多细节 syft-json
  4. 过滤与配置
    syft 提供了丰富的选项来过滤扫描内容或调整输出。

    • 排除文件/目录

      # 排除 vendor 目录 (如果使用 Go Modules vendor 模式)
      syft dir . --exclude vendor/ -o spdx-json > my-go-app-spdx.json
      
      # 排除特定文件类型
      syft dir . --exclude "*.test" -o spdx-json
    • 仅包含特定类型包
      # 仅包含 Go 模块
      syft dir . --scope=all-layers --package-type=go-module -o cyclonedx-json
    • 生成最小 SBOM (仅包含直接依赖)
      这通常不是推荐做法,因为间接依赖也可能存在漏洞。但如果出于特殊目的,可以尝试:
      syft 默认会尝试包含所有可检测到的依赖。要严格限制,可能需要后处理 SBOM 文件或使用更复杂的过滤规则。对于 Go 模块,syft 已经做得很好,会自动解析 go.sum 中的所有传递性依赖。

    扫描编译后的二进制文件 (Go)
    由于 Go 默认静态链接,将所有依赖编译到单个二进制文件中,这使得从二进制文件逆向推导依赖变得困难。syft 能够尝试识别一些 Go 模块信息,但其准确性和完整性可能不如直接扫描 go.mod/go.sum

    go build -o my-go-app
    syft file my-go-app -o cyclonedx-json > my-go-app-binary-cyclonedx.json

    比较 my-go-app-cyclonedx.jsonmy-go-app-binary-cyclonedx.json,您会发现直接扫描源码目录(包含 go.mod)生成的 SBOM 会更完整和准确。因此,推荐在构建前或构建时,直接扫描 Go 项目的源码目录

C. 其他 Go-specific 或集成工具

虽然 syft 是一个通用且强大的 SBOM 生成工具,但也有一些 Go 生态系统内的工具值得关注。例如,govulncheck (我们稍后会详细介绍) 主要用于漏洞扫描,而不是 SBOM 生成。它关注的是 Go 模块的已知漏洞,并能精确到函数调用级别,但它不直接输出标准的 SBOM 格式。因此,在 Go 项目中,syft 仍然是生成标准 SBOM 的首选工具。

D. 将 SBOM 生成集成到本地构建流程

将 SBOM 生成集成到本地构建流程是实现自动化的第一步。

  1. Makefile 示例
    my-go-app 目录下创建 Makefile

    .PHONY: build clean sbom
    
    APP_NAME := my-go-app
    SBOM_FILE_SPDX := $(APP_NAME)-spdx.json
    SBOM_FILE_CYCLONEDX := $(APP_NAME)-cyclonedx.json
    
    # 默认构建目标
    build: $(APP_NAME) sbom
    
    $(APP_NAME): main.go
        @echo "Building $(APP_NAME)..."
        go build -o $@ .
        @echo "Build complete."
    
    sbom:
        @echo "Generating SBOMs..."
        syft dir . -o spdx-json > $(SBOM_FILE_SPDX)
        syft dir . -o cyclonedx-json > $(SBOM_FILE_CYCLONEDX)
        @echo "SPDX SBOM generated: $(SBOM_FILE_SPDX)"
        @echo "CycloneDX SBOM generated: $(SBOM_FILE_CYCLONEDX)"
    
    clean:
        @echo "Cleaning up..."
        rm -f $(APP_NAME) $(SBOM_FILE_SPDX) $(SBOM_FILE_CYCLONEDX)
        @echo "Cleanup complete."

    现在,只需运行 make,就可以同时构建应用程序并生成 SBOM。

    make
  2. 脚本化生成
    对于更复杂的场景或非 Makefile 项目,可以使用 shell 脚本来自动化这个过程:
    generate_sbom.sh:

    #!/bin/bash
    
    APP_NAME="my-go-app"
    OUTPUT_DIR="./sbom-output"
    
    mkdir -p "$OUTPUT_DIR"
    
    echo "Generating SPDX JSON SBOM for $APP_NAME..."
    syft dir . -o spdx-json > "$OUTPUT_DIR/$APP_NAME-spdx.json"
    if [ $? -ne 0 ]; then
        echo "Error generating SPDX SBOM. Exiting."
        exit 1
    fi
    echo "SPDX SBOM saved to $OUTPUT_DIR/$APP_NAME-spdx.json"
    
    echo "Generating CycloneDX JSON SBOM for $APP_NAME..."
    syft dir . -o cyclonedx-json > "$OUTPUT_DIR/$APP_NAME-cyclonedx.json"
    if [ $? -ne 0 ]; then
        echo "Error generating CycloneDX SBOM. Exiting."
        exit 1
    fi
    echo "CycloneDX SBOM saved to $OUTPUT_DIR/$APP_NAME-cyclonedx.json"
    
    echo "SBOM generation complete."

    运行脚本:

    chmod +x generate_sbom.sh
    ./generate_sbom.sh

    这些本地集成方法是为 CI/CD 自动化打下基础的关键步骤。

V. 利用 SBOM 审计第三方依赖的安全风险

生成 SBOM 只是第一步,真正的价值在于如何利用它来持续审计和管理安全风险。这一阶段通常涉及将 SBOM 与漏洞数据库进行比对,以识别已知漏洞。

A. 漏洞数据源:NVD, OSV, GHSA

审计 SBOM 需要权威的漏洞数据来源:

  1. NVD (National Vulnerability Database)

    • 由美国国家标准与技术研究院 (NIST) 维护,是全球最主要的公共漏洞数据库之一。
    • 它聚合了来自 CVE (Common Vulnerabilities and Exposures) 项目的漏洞信息,并提供了额外的分析,包括漏洞类型、影响范围、修复建议以及 CVSS (Common Vulnerability Scoring System) 评分。
    • 缺点是更新可能不够及时,且有时粒度不够细致。
  2. OSV (Open Source Vulnerabilities)

    • 由 Google 主导的开源项目,旨在提供更准确、更及时的开源软件漏洞信息。
    • OSV 的特点是数据以 git 仓库的形式组织,更容易被自动化工具消费。
    • 它强调漏洞的“可到达性”,即某个漏洞是否真的会影响到使用该组件的代码。
    • 对于 Go 项目,OSV 数据库包含了 Go 官方维护的漏洞信息。
  3. GHSA (GitHub Security Advisories)

    • GitHub 维护的漏洞数据库,包含了 GitHub 上托管的开源项目发现的漏洞。
    • 这些安全通告通常与 GitHub 的 Dependabot 警报集成,可以直接通知项目维护者。
    • GHSA 数据也经常被聚合到 NVD 和 OSV 等其他数据库中。
  4. 漏洞标识符 (CVE)

    • CVE 是一个国际标准,为每个已公开的安全漏洞分配一个唯一的标识符(例如 CVE-2021-44228)。
    • 通过 CVE ID,可以跨不同的数据库和工具追踪同一个漏洞。
  5. 漏洞严重性 (CVSS)

    • CVSS 提供了一种开放的、通用的漏洞严重性评分方法。
    • 它根据漏洞的可利用性、影响范围、所需权限等因素,计算出一个 0-10 的分数,并分为低、中、高、严重四个等级。
    • CVSS 评分帮助组织优先处理最关键的漏洞。

B. 自动化漏洞扫描工具 grype 深度解析

grype 是 Anchore 公司开发的另一个开源工具,与 syft 紧密集成。它能够以 syft 生成的 SBOM 作为输入,对照多个漏洞数据库进行扫描,并生成详细的漏洞报告。

  1. grype 的工作原理:如何与 SBOM 结合

    • grype 维护了一个本地的漏洞数据库缓存(从 NVD、OSV、GHSA 等源同步)。
    • 当接收到 SBOM 时,grype 会解析 SBOM 中的每个组件(名称、版本、PURL 等)。
    • 然后,它会查询本地漏洞数据库,查找与 SBOM 中组件匹配的已知漏洞。
    • 匹配成功后,grype 会生成一个详细的报告,列出受影响的组件、漏洞 ID (CVE)、CVSS 评分、漏洞描述和建议的修复版本。
  2. 安装与基本使用
    grype 的安装方式与 syft 类似。

    安装 grype (Linux/macOS):

    # 使用 Homebrew (macOS/Linux)
    brew install grype
    
    # 或者使用 Go 安装 (可能需要手动配置PATH)
    go install github.com/anchore/grype/cmd/grype@latest
    
    # 或者从 GitHub Release 下载二进制文件并添加到 PATH
    # 访问 https://github.com/anchore/grype/releases 下载适合您系统的版本

    验证安装:

    grype version
    # 例如输出: grype v0.70.0

    示例:扫描 syft 生成的 SBOM
    我们使用之前为 my-go-app 生成的 my-go-app-spdx.json 文件。

    grype sbom:my-go-app-spdx.json

    sbom: 前缀告诉 grype 输入是一个 SBOM 文件。grype 将会下载并更新其漏洞数据库,然后对 SBOM 进行扫描。
    输出将会是一个表格形式的报告,列出发现的所有漏洞。

    直接扫描 Go 项目 (背后的机制)
    grype 也可以直接扫描目录或容器镜像,而无需预先运行 syft。在这种情况下,grype 会在内部调用 syft 来生成一个临时的 SBOM,然后对其进行扫描。

    grype dir .

    这与 syft dir . -o syft-json | grype sbom:- (通过管道传输 syftsyft-json 输出到 grype 的标准输入) 的效果类似。直接使用 grype dir . 更方便,但理解其内部机制有助于在 CI/CD 中进行更精细的控制。

  3. 过滤与报告
    grype 提供了强大的过滤和报告功能。

    • 按严重性过滤
      您可能只关心高危或严重漏洞。

      # 只显示严重 (Critical) 和高危 (High) 漏洞
      grype sbom:my-go-app-spdx.json --severity Critical --severity High

      grype 支持 Critical, High, Medium, Low, Negligible, Unknown 等严重性级别。

    • 输出格式 (JSON, CycloneDX, SPDX)
      除了默认的表格输出,grype 也可以输出机器可读的格式,便于集成到其他安全工具或仪表板中。

      # 输出 JSON 格式报告
      grype sbom:my-go-app-spdx.json -o json > my-go-app-vulnerabilities.json
      
      # 输出 CycloneDX 格式报告 (包含漏洞信息)
      grype sbom:my-go-app-spdx.json -o cyclonedx-json > my-go-app-vulnerabilities-cyclonedx.json
      
      # 输出 SPDX 格式报告 (包含漏洞信息)
      grype sbom:my-go-app-spdx.json -o spdx-json > my-go-app-vulnerabilities-spdx.json
    • 生成 SARIF 报告
      SARIF (Static Analysis Results Interchange Format) 是一种用于静态分析结果的通用格式,被许多安全工具和平台支持,包括 GitHub Code Scanning。

      grype sbom:my-go-app-spdx.json -o sarif > my-go-app-vulnerabilities.sarif

      这将生成一个 SARIF 文件,可以上传到 GitHub 或其他兼容 SARIF 的平台进行展示和管理。

  4. 配置 grype:自定义漏洞源、排除项
    grype 支持通过配置文件进行更高级的配置。

    • 自定义漏洞源:可以配置 grype 从私有漏洞数据库或特定的 OSV 仓库获取数据。
    • 排除项:可以排除特定的 CVE ID,或排除特定组件的漏洞(例如,如果您知道某个组件的漏洞在您的特定使用场景下不会被触发)。
      grype.yaml:

      # .grype.yaml
      ignore:
        - vulnerability: CVE-2022-XXXXX # 忽略某个特定的CVE
          reason: "False positive"
        - vulnerability: CVE-YYYY-YYYYY
          package:
            name: "github.com/some/package" # 忽略某个包的特定CVE
            version: "1.2.3"
          reason: "Mitigated by configuration"
        - package:
            name: "github.com/another/package" # 忽略某个包的所有漏洞
          reason: "Internal package, not exposed"

      然后运行 grype 并指定配置文件:

      grype sbom:my-go-app-spdx.json --config .grype.yaml

C. Go 语言原生漏洞检查工具 govulncheck

govulncheck 是 Go 团队推出的一款专门用于 Go 模块的漏洞检查工具。它与 grype 等通用工具形成互补,提供了 Go 语言特有的优势。

  1. govulncheck 的独特优势:基于调用图的精确性

    • govulncheck 的核心优势在于它能够分析 Go 程序的调用图 (call graph)。
    • 这意味着它不仅会报告项目中存在的漏洞包,还会进一步检查您的代码是否实际调用了包含漏洞的函数。
    • 这种“可到达性”分析大大减少了误报,使开发人员能够专注于真正影响其应用程序的漏洞。例如,如果一个库中有一个漏洞函数,但您的代码从未调用它,govulncheck 就不会将其标记为直接风险。
    • 它利用 Go 官方维护的 Go Vulnerability Database (GoVulnDB),这个数据库包含了 Go 模块特有的漏洞信息。
  2. 安装与使用
    govulncheck 是 Go 官方工具链的一部分,Go 1.18 及以上版本可以通过 go install 安装。

    go install golang.org/x/vuln/cmd/govulncheck@latest

    my-go-app 目录下运行:

    govulncheck ./...

    或者直接扫描二进制文件:

    go build -o my-go-app
    govulncheck ./my-go-app

    govulncheck 会输出发现的漏洞列表,并指示漏洞是否在您的代码中被实际调用。

    示例输出 (假设存在漏洞):

    # govulncheck ./...
    Vulnerability #1: GO-2022-0001
      github.com/gin-gonic/gin before v1.7.0 is vulnerable to ...
      Found in: github.com/gin-gonic/[email protected]
      Call stacks:
        ...
        main.main calls github.com/gin-gonic/gin.(*Engine).Run
        ...

    如果一个漏洞存在于依赖中,但没有实际的调用栈,govulncheck 也会报告,但会明确指出“Found in (not called)”,帮助您区分风险。

  3. 与 SBOM 工具的互补性

    • govulncheck 关注 Go 模块的已知漏洞和实际使用情况:它提供了 Go 项目特有的精确度,帮助开发人员聚焦于最相关的漏洞。
    • grype/syft 提供更全面的 SBOM 和漏洞信息
      • syft 生成的 SBOM 不仅包含 Go 模块,还可能包含操作系统包、配置文件等其他组件。
      • grype 扫描的漏洞数据库更广泛,不仅限于 Go 官方维护的漏洞。
      • grype 的输出是标准化的 SBOM 格式,更利于与下游工具集成。

    最佳实践是结合使用它们

    • 在 CI/CD 中,首先使用 syft 生成一个全面的 SBOM。
    • 然后使用 grype 对这个 SBOM 进行通用漏洞扫描,以发现所有已知组件的漏洞。
    • 对于 Go 项目,额外运行 govulncheck 进行一次 Go 语言特有的精确性检查,以识别那些实际可达的 Go 模块漏洞。
    • 这样可以获得最全面的覆盖和最精确的报告。

D. 漏洞处理与修复策略

发现漏洞后,下一步是进行处理。

  1. 升级依赖
    这是最常见和最推荐的修复方式。大多数漏洞都会有上游修复版本。

    go get github.com/gin-gonic/gin@latest
    go mod tidy

    升级后,重新生成 SBOM 并进行扫描,以确认漏洞已解决。

  2. 临时缓解措施
    如果无法立即升级(例如,升级会导致兼容性问题),可能需要采取临时缓解措施:

    • 禁用受影响的功能。
    • 配置 WAF (Web Application Firewall) 或其他安全控制来阻止对漏洞的利用。
    • 打补丁 (patch) 依赖库的源代码(不推荐,除非别无选择,且需谨慎管理)。
    • 隔离受影响的服务。
      这些措施通常是临时的,最终目标仍是升级。
  3. 接受风险 (附带文档说明)
    在某些罕见情况下,如果漏洞的 CVSS 评分较低,或者您能明确证明漏洞在您的特定部署环境中无法被利用(例如,漏洞存在于您从未使用的代码路径中,或者有其他安全控制可以完全阻断攻击),您可以选择接受风险。
    重要提示:这必须是一个经过深思熟虑的决定,并需要详细的文档说明,包括风险分析、缓解措施和批准人。在 grype 中可以使用 ignore 配置来标记这些已接受的漏洞。

VI. 将 SBOM 审计集成到 CI/CD 流水线

将 SBOM 生成和漏洞审计集成到 CI/CD (Continuous Integration/Continuous Delivery) 流水线是自动化软件供应链安全的关键步骤。这确保了每次代码提交或构建都会自动进行安全检查。

A. CI/CD 集成的必要性

  • 持续安全:在开发生命周期的早期发现并修复问题,遵循“左移 (Shift Left)”原则。
  • 自动化与一致性:消除手动操作的错误和遗漏,确保每次构建都遵循相同的安全标准。
  • 及时反馈:快速将漏洞信息反馈给开发团队,加速修复周期。
  • 合规性证明:每次构建都生成 SBOM 和扫描报告,为合规性审计提供证据。
  • 阻止不安全部署:配置流水线在发现严重漏洞时阻止部署,防止不安全软件进入生产环境。

B. 典型 CI/CD 流程中的 SBOM 步骤

SBOM 生成和审计可以放置在 CI/CD 流水线的不同阶段:

  1. 构建前 (Pre-Build)

    • 在编译或打包之前,分析 go.mod 文件生成 SBOM。这确保了 SBOM 准确反映了依赖的原始状态。
    • 对 SBOM 进行初步漏洞扫描。
  2. 构建后 (Post-Build)

    • 如果应用程序被打包成容器镜像,可以在镜像构建完成后,对容器镜像进行扫描以生成 SBOM,并进行漏洞审计。这能捕获操作系统层面的依赖和漏洞。
    • 或者,对编译后的二进制文件或部署包进行 SBOM 生成和漏洞扫描 (Go 项目推荐扫描源码目录)。
  3. 部署前 (Pre-Deployment)

    • 在将应用程序部署到生产环境之前,再次进行 SBOM 审计,特别是对于长期运行的应用程序,以捕获在构建后新发现的漏洞。

C. GitHub Actions 示例

GitHub Actions 是一种流行的 CI/CD 平台,我们可以用它来自动化 SBOM 的生成和审计。

假设我们的 Go 项目在 GitHub 仓库中。

.github/workflows/sbom-audit.yml:

name: Go SBOM Generation and Vulnerability Audit

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main
  workflow_dispatch: # 允许手动触发

jobs:
  build-and-audit:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Set up Go
        uses: actions/setup-go@v4
        with:
          go-version: '1.21'
          cache: true # 缓存 Go 模块以加速构建

      - name: Install Go dependencies
        run: go mod tidy

      - name: Build Go application
        run: go build -o my-go-app .

      - name: Install Syft
        uses: anchore/[email protected]
        with:
          version: 'latest' # 确保使用最新版 syft

      - name: Generate SBOM (CycloneDX JSON)
        id: generate_sbom
        run: |
          syft dir . -o cyclonedx-json > my-go-app-cyclonedx.json
          echo "SBOM_PATH=$(pwd)/my-go-app-cyclonedx.json" >> $GITHUB_ENV
        env:
          # 确保 syft 能够识别 go 模块
          SYFT_GO_MOD_ENABLED: "true"

      - name: Upload SBOM as artifact
        uses: actions/upload-artifact@v3
        with:
          name: sbom-cyclonedx
          path: my-go-app-cyclonedx.json

      - name: Install Grype
        uses: anchore/[email protected]
        with:
          version: 'latest' # 确保使用最新版 grype

      - name: Scan SBOM for vulnerabilities
        id: scan_sbom
        # 使用 syft 生成的 SBOM 进行扫描
        # --fail-on 选项可以配置在检测到特定严重性漏洞时使构建失败
        run: |
          grype sbom:"${{ env.SBOM_PATH }}" -o cyclonedx-json > my-go-app-vulnerabilities-cyclonedx.json
          # 如果需要 SARIF 格式用于 GitHub Code Scanning,可以额外生成
          # grype sbom:"${{ env.SBOM_PATH }}" -o sarif > my-go-app-vulnerabilities.sarif

      - name: Upload Vulnerability Report as artifact
        uses: actions/upload-artifact@v3
        with:
          name: vulnerability-report-cyclonedx
          path: my-go-app-vulnerabilities-cyclonedx.json
          # path: my-go-app-vulnerabilities.sarif # 如果生成了 SARIF

      - name: Run GoVulnCheck
        run: |
          govulncheck ./... || true # 允许 govulncheck 失败,但继续执行流水线,根据需要可以修改为严格模式
        env:
          # 设置 Go 的路径,govulncheck 依赖于此
          GOVULNCHECK_DATABASE: https://vuln.go.dev/
          GO111MODULE: on

      - name: Check for critical vulnerabilities and fail build (example)
        # 这是一个示例,您需要根据实际的漏洞报告来解析并决定是否失败
        # 更健壮的方法是解析 grype 的 JSON 输出或 SARIF 报告
        run: |
          # 假设我们想检查是否有任何 critical 或 high 漏洞,如果有则失败
          # 这是一个简化示例,实际生产中需要更复杂的脚本来解析 JSON 报告
          VULN_COUNT=$(cat my-go-app-vulnerabilities-cyclonedx.json | jq '.vulnerabilities | length')
          if [ "$VULN_COUNT" -gt 0 ]; then
            echo "Found $VULN_COUNT vulnerabilities. Checking severity..."
            # 进一步解析 JSON 报告,查找 Critical/High 漏洞
            CRITICAL_HIGH_COUNT=$(cat my-go-app-vulnerabilities-cyclonedx.json | jq '[.vulnerabilities[] | select(.severity | IN("CRITICAL", "HIGH"))] | length')
            if [ "$CRITICAL_HIGH_COUNT" -gt 0 ]; then
              echo "::error::Found $CRITICAL_HIGH_COUNT CRITICAL/HIGH vulnerabilities. Failing build."
              exit 1
            else
              echo "No CRITICAL/HIGH vulnerabilities found, but other severities exist. Build continues."
            fi
          else
            echo "No vulnerabilities found."
          fi
        # 需要安装 jq 来解析 JSON
        # uses: docker://alpine/git:latest # 或者在 setup-go 之后添加 apt install jq

      # 如果您希望在发现漏洞时直接失败,可以使用 grype 的 --fail-on 选项
      # - name: Scan SBOM for vulnerabilities with fail-on
      #   id: scan_sbom_fail_on
      #   run: grype sbom:"${{ env.SBOM_PATH }}" --fail-on Critical --fail-on High
      #   continue-on-error: false # 如果 grype 失败,整个 job 失败

这个 GitHub Actions 脚本的流程是:

  1. 拉取代码。
  2. 设置 Go 环境,安装依赖并构建应用程序。
  3. 安装 syft,并使用它生成 my-go-app 的 CycloneDX 格式 SBOM。
  4. 将 SBOM 作为构建产物 (artifact) 上传,方便后续下载和分析。
  5. 安装 grype,并使用 SBOM 进行漏洞扫描,生成 CycloneDX 格式的漏洞报告。
  6. 将漏洞报告作为构建产物上传。
  7. 运行 govulncheck 进行 Go 语言特有的漏洞分析。
  8. 关键步骤:添加了一个条件检查,如果 grype 报告中包含 Critical 或 High 严重性的漏洞,则使整个 GitHub Actions 任务失败。这有效地阻止了不安全的软件发布。

D. GitLab CI/CD 示例

GitLab CI/CD 也提供了类似的集成能力。

.gitlab-ci.yml:

stages:
  - build
  - sbom_audit

variables:
  GO_VERSION: "1.21"
  APP_NAME: "my-go-app"
  SBOM_FILE_CYCLONEDX: "${APP_NAME}-cyclonedx.json"
  VULN_REPORT_CYCLONEDX: "${APP_NAME}-vulnerabilities-cyclonedx.json"

build_job:
  stage: build
  image: golang:${GO_VERSION}-alpine
  script:
    - apk add --no-cache git # 安装 git 用于 go mod tidy
    - go mod tidy
    - go build -o ${APP_NAME} .
  artifacts:
    paths:
      - ${APP_NAME}
      - go.mod
      - go.sum
    expire_in: 1 week

sbom_audit_job:
  stage: sbom_audit
  image: docker.io/anchore/grype:latest # 使用包含 syft 和 grype 的镜像
  dependencies:
    - build_job # 依赖于构建阶段
  script:
    - echo "Generating SBOM using Syft..."
    - syft dir . -o cyclonedx-json > ${SBOM_FILE_CYCLONEDX}
    - echo "Scanning SBOM for vulnerabilities using Grype..."
    # 使用 --fail-on 选项,在发现高危或严重漏洞时使 job 失败
    - grype sbom:${SBOM_FILE_CYCLONEDX} --fail-on Critical --fail-on High -o cyclonedx-json > ${VULN_REPORT_CYCLONEDX}
    # 运行 govulncheck
    # - /usr/local/go/bin/go install golang.org/x/vuln/cmd/govulncheck@latest # 需要安装 go 环境才能运行
    # - /go/bin/govulncheck ./... || true # 假设 go 安装在 /usr/local/go
  artifacts:
    paths:
      - ${SBOM_FILE_CYCLONEDX}
      - ${VULN_REPORT_CYCLONEDX}
    expire_in: 1 week
  allow_failure: false # 如果 grype 因漏洞而失败,则整个 job 失败

这个 GitLab CI 示例使用了 Anchore 提供的包含 syftgrype 的 Docker 镜像,简化了工具安装。allow_failure: false 结合 grype --fail-on 实现了在检测到关键漏洞时阻止流水线继续执行的功能。

E. Jenkins Pipeline 示例 (简要提及)

在 Jenkins Pipeline 中,您可以将 syftgrype 命令集成到 script 块中,或者使用 Docker 代理来运行这些工具。

pipeline {
    agent {
        docker {
            image 'golang:1.21-alpine'
            args '-v /var/run/docker.sock:/var/run/docker.sock' // 如果需要扫描容器镜像
        }
    }
    environment {
        APP_NAME = "my-go-app"
        SBOM_FILE_CYCLONEDX = "${APP_NAME}-cyclonedx.json"
        VULN_REPORT_CYCLONEDX = "${APP_NAME}-vulnerabilities-cyclonedx.json"
    }
    stages {
        stage('Build') {
            steps {
                sh 'go mod tidy'
                sh "go build -o ${APP_NAME} ."
            }
        }
        stage('Generate SBOM and Audit') {
            agent {
                docker {
                    image 'anchore/grype:latest' // 使用 Anchore 的复合镜像
                    args '-v /var/run/docker.sock:/var/run/docker.sock'
                }
            }
            steps {
                script {
                    sh "syft dir . -o cyclonedx-json > ${SBOM_FILE_CYCLONEDX}"
                    // 使用 try-catch 块来捕获 grype 失败,并决定是否中断 pipeline
                    try {
                        sh "grype sbom:${SBOM_FILE_CYCLONEDX} --fail-on Critical --fail-on High -o cyclonedx-json > ${VULN_REPORT_CYCLONEDX}"
                        echo "No Critical/High vulnerabilities found, continuing."
                    } catch (e) {
                        echo "Found Critical/High vulnerabilities. Failing pipeline."
                        currentBuild.result = 'FAILURE'
                        error "Vulnerabilities found: ${e.message}"
                    }
                    // govulncheck 可以在 golang 镜像中运行
                    // sh "go install golang.org/x/vuln/cmd/govulncheck@latest"
                    // sh "govulncheck ./..."
                }
                archiveArtifacts artifacts: "${SBOM_FILE_CYCLONEDX}, ${VULN_REPORT_CYCLONEDX}"
            }
        }
    }
}

F. 报告与通知:如何将结果反馈给开发团队

  • CI/CD 仪表板:大多数 CI/CD 系统都会显示任务的成功或失败状态,以及日志输出。
  • Artifacts:将 SBOM 和漏洞报告作为构建产物,方便开发人员下载查看。
  • 安全扫描集成:将 SARIF 报告上传到 GitHub Code Scanning 或其他 SAST/DAST 平台,集中管理和展示安全问题。
  • 通知:通过邮件、Slack、Microsoft Teams 等通知渠道,将关键漏洞警报发送给相关的开发团队或安全团队。
  • 集中式安全平台:对于大型组织,可以集成像 Anchore Enterprise、Dependency-Track 等专业的供应链安全平台,它们可以摄入 SBOM 和漏洞报告,提供统一的视图、策略管理和风险评估。

VII. SBOM 最佳实践与未来展望

A. 最佳实践

  1. 版本控制 SBOM:与代码版本同步
    将生成的 SBOM 文件与您的应用程序代码一起进行版本控制(例如,提交到 Git 仓库)。这样,每个代码版本都有一个对应的 SBOM,便于追溯。

  2. 存储与分发 SBOM:安全、可访问

    • 将 SBOM 存储在安全且可审计的位置(例如,对象存储、制品库)。
    • 确保 SBOM 在需要时可以被消费者或审计员访问。
    • 考虑使用 OCI 注册表来存储 SBOM,就像存储容器镜像一样。
  3. 签名 SBOM:确保完整性与来源
    使用数字签名来证明 SBOM 的完整性和来源。这意味着 SBOM 在生成后未被篡改,并且确实由声称的实体生成。cosign 等工具可以用于对 SBOM 文件进行签名。

  4. 涵盖所有组件:包括操作系统、运行时、工具链
    一个理想的 SBOM 不仅包含应用程序依赖,还应包含构建应用程序所用的所有环境组件:

    • 操作系统包 (如果应用程序运行在容器中)。
    • 编程语言运行时 (Go 版本)。
    • 编译器和构建工具 (如 make, go 工具链)。
    • 基础镜像中的所有组件。
      syft 在扫描容器镜像时可以很好地捕获这些信息。
  5. 持续更新与再生成
    软件依赖是动态变化的,新的漏洞每天都在被发现。因此,SBOM 应该定期重新生成和扫描。每次代码变更、依赖更新、新漏洞披露时,都应触发 SBOM 的更新和审计。

  6. 与许可证合规性的协同
    虽然本次讲座侧重安全,但 SBOM 中的许可证信息对于许可证合规性同样重要。在集成 SBOM 工具时,也可以考虑其对许可证检测的支持,实现安全与合规的双重管理。

B. 挑战与发展方向

  1. SBOM 的自动化生成与更新精度
    虽然 syft 等工具已经非常强大,但在某些复杂场景下(如动态加载的库、混淆代码、非常规的构建系统),生成 100% 准确和完整的 SBOM 仍然是一个挑战。未来工具需要更高的智能性和更广泛的覆盖。

  2. 运行时 SBOM 与动态分析
    当前的 SBOM 主要反映的是软件在构建时的静态构成。然而,软件在运行时可能会动态加载组件、使用不同的配置或与外部服务交互。未来的趋势是探索如何生成“运行时 SBOM”或将其与动态分析技术结合,以提供更全面的运行时安全视图。

  3. 供应链攻击的复杂性
    攻击者也在不断进化,可能通过更隐蔽的方式渗透供应链。例如,利用包管理器中的命名冲突 (typosquatting)、依赖混淆 (dependency confusion) 等。SBOM 需要不断发展,以应对这些新型攻击。

  4. 跨组织 SBOM 共享与验证
    在一个复杂的供应链中,一个产品可能包含来自多个供应商的组件。如何安全、高效、可信地共享和验证跨组织生成的 SBOM 是一个重要的挑战。需要更强的标准化、签名机制和信任根。

  5. SBOM 与 attestation (证明)
    除了 SBOM 本身,软件的“证明”也越来越受到关注。证明是关于软件如何构建、测试、签名的元数据。例如,SLSA (Supply-chain Levels for Software Artifacts) 框架就是一个旨在提高软件供应链完整性的标准,它强调通过构建过程的透明度和不可篡改性来增强信任。SBOM 可以作为这些证明的重要组成部分。

VIII. 确保软件供应链安全,从 SBOM 开始

在软件日益成为社会基础设施核心的今天,软件供应链安全已不再是可选项,而是强制要求。Software Bill of Materials (SBOM) 作为一种基础性工具,为我们提供了前所未有的透明度和可追溯性,是构建安全软件供应链的基石。

通过本次讲座,我们深入了解了 SBOM 的概念、主流标准,并通过 syftgrypegovulncheck 等工具,演示了如何在 Go 项目中自动化生成 SBOM 并审计第三方依赖的安全风险。我们还探讨了如何将这些流程无缝集成到 CI/CD 流水线中,并讨论了 SBOM 的最佳实践和未来趋势。

请记住,SBOM 不是一劳永逸的解决方案,而是一个持续的实践。它需要您在整个软件开发生命周期中,从设计、开发、构建、测试到部署和运营,都保持对组件透明度和安全风险的关注。从今天开始,将 SBOM 引入您的 Go 项目,将是您迈向更安全、更可信赖软件之旅的重要一步。

感谢各位的参与!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注