首页
/ Trivy 对 Conda 包扫描的完整指南:conda-meta 元数据与 environment.yml 的 SBOM 与 License 检测

Trivy 对 Conda 包扫描的完整指南:conda-meta 元数据与 environment.yml 的 SBOM 与 License 检测

2026-09-08 18:22:03作者:沈韬淼Beryl

Trivy 内置了对 Anaconda / Miniconda(Conda)包生态的扫描支持。本篇指南围绕 conda.md 展开,系统讲解 Trivy 如何解析 conda-meta/<package>.json 元数据文件与 environment.yml 环境描述文件,实现 SBOM(软件物料清单)生成与 License(许可证)检测,并说明其中对版本范围的限制、prefix 字段的语义以及对应的源码实现路径。读完本文,你将能够准确判断何种 Conda 扫描场景适用 Trivy,并掌握正确的数据准备流程(如使用 conda env export 固定依赖版本)以获得完整、准确的扫描结果。

支持能力总览

Trivy 对 Conda 包的扫描能力可通过下表速览(与官方文档一致):

Scanner 是否支持
SBOM
Vulnerability(漏洞) -
License(许可证)

也就是说,Trivy 可以把 Conda 环境中的已安装包完整盘点为 SBOM 并识别其许可证,但当前不提供对 Conda 包本身的漏洞匹配扫描,从 pkg/detector 的目录结构(其中并不包含 Conda 的漏洞比对驱动)也能印证这一点。

针对两种输入文件,Trivy 的支持矩阵如下:

包管理器 文件 传递依赖 开发依赖 依赖图 位置信息 检测优先级
Conda environment.yml - 包含 - -

术语解释(点击可查看 Trivy 中对应配置):依赖图 指报告中显示漏洞依赖来源(Origins)的能力;检测优先级 指多个检测器命中同一包时如何决定使用哪个检测结果。Conda 支持在报告中输出依赖的位置(Position)信息,但不参与依赖图溯源与检测优先级判定。

Trivy 对 Conda 的处理分为两种输入形态,两条独立的代码链路分别在 pkg/fanal/analyzer/language/conda/ 下:

  1. meta/ 分析器:识别 conda-meta/<package>.json(每个已安装包一份 JSON 元数据);
  2. environment/ 分析器:识别 environment.yml(整个 Conda 环境的人工可读描述)。

两者在 SBOM 输出上互补:前者直接逐包读取精确版本,后者仅能列出依赖清单,精确版本与许可证需要结合前者的元数据(通过 prefix 字段定位)才能补齐。

<package>.json:conda-meta 元数据扫描

SBOM:逐包读取已安装依赖

Conda 在创建每个环境时,会在 <conda-root>/envs/<env>/conda-meta/ 目录下为每个安装的包生成一份 <package>.json 文件。Trivy 通过解析这些文件还原环境中的依赖列表。

对应的实现位于 pkg/fanal/analyzer/language/conda/meta/meta.go,其匹配正则限制了候选文件路径:

var fileRegex = regexp.MustCompile(`.*/envs/.+/conda-meta/.+-.+-.+\.json`)

即只有路径中包含 envs/<env>/conda-meta/,且文件名符合 <包名>-<版本>-<构建串>.json 三段式约定的文件才会被分析,例如 bzip2-1.0.8-h5eee18b_6.jsonconda env export 生成的 conda-meta 目录天然符合该结构,因此无需任何额外配置。

实际解析逻辑在 pkg/dependency/parser/conda/meta/parse.go,它只关心 JSON 中的三个顶层字段:

type packageJSON struct {
    Name    string `json:"name"`
    Version string `json:"version"`
    License string `json:"license"`
}

如果 nameversion 为空,解析器会直接判定该文件不是合法的 Conda 包元数据并报错;只有两者都存在的包才会被收录进扫描结果。以仓库中自带的样例数据 libgomp-11.2.0-h1234567_1.json 为例,其结构形如:

{
  "name": "libgomp",
  "version": "11.2.0",
  "build": "h1234567_1",
  "license": "GPL-3.0-only WITH GCC-exception-3.1",
  ...
}

License:元数据自带许可证

由于 <package>.json 元数据本身就携带 license 字段(如上例中的 GPL-3.0-only WITH GCC-exception-3.1),Trivy 无需再解析额外文件即可为每个包附上许可证信息。许可证字符串会经过 licensing.SplitLicenses 拆分处理(见 parse.go),以兼容同一字段中包含多个许可证表达式的情况。

environment.yml:环境描述文件扫描

SBOM:解析依赖清单

environment.ymlyamlyml 扩展名均受支持,见 environment.goCondaEnvYml / CondaEnvYaml 的判断)是 Conda 官方推荐的“分享环境”方式,用于声明环境所需的依赖。Trivy 的 environment/ 分析器可解析其中的 dependencies 列表,将其转换为 SBOM 中的包集合。

对应的 YAML 解析器位于 pkg/dependency/parser/conda/environment/parse.go,它支持两种 dependencies 条目:

  • 纯字符串条目,例如 - numpy=1.8.1=py27_0
  • 嵌套子依赖组(常见于 pip),例如:
dependencies:
  - pip:
      - django==5.0.6

解析器会把每个条目转换为“包名 + 精确版本 + 在文件中的行号(Location)”,行号信息即上文矩阵中“位置”一列的数据来源。

版本范围限制与 conda env export

environment.yml 支持声明[版本范围][env-version-range],但版本范围无法被解析为确定的包版本。在 parse.go 的实现注释中明确写到:版本范围不被支持,只解析固定版本(pinned version)。仓库自带的 happy.yaml 样例展示了各种可能的书写形式:

dependencies:
  - blas=1.0=openblas            # 固定版本
  - ca-certificates=2024.2       # 固定版本
  - ld_impl_linux-aarch64=2.40.* # 通配,无法确认精确版本
  - libblas>=3.9                 # 范围,无法确认精确版本
  - libgcc-ng 13.2|13.3          # 多候选,无法确认精确版本
  - libexpat==2.6.2              # 固定版本
  - libffi==3.4.2=h3557bc0_5
  - libgomp 13.2.0 hf8544c7_5    # 固定版本
  - pip:
      - django==5.0.6

因此在扫描 environment.yml 前,官方建议先执行 conda env export 命令,将其输出保存为环境描述文件。conda env export 会为每个依赖写出固定版本,从而让 Trivy 能获得精确的版本号:

conda env export > environment.yml

注意:对于非 Conda 格式的依赖(例如上述 pip: 子依赖),只要未固定精确版本,Trivy 就不会为其填充版本号。

当一个依赖没有可解析的精确版本时,解析器只记录包名、丢弃版本,并输出一条警告日志,提示使用 conda env export 固定版本(对应 parse.go 中的 Warn 逻辑)。

License:经 prefix 目录回查 conda-meta

与直接解析 <package>.json 不同,environment.yml 本身并不携带任何许可证信息。Trivy 的做法是:读取环境描述中的 prefix 字段,把它视为 Conda 环境根目录,再到 <prefix>/conda-meta/ 下按 pkg.Name-pkg.Version-*.json 的 glob 模式(由 findLicenseFromEnvDir 使用 doublestar 匹配)定位对应的元数据文件,从而回查出许可证。

上述逻辑也意味着两个前提条件缺一不可:

  1. environment.yml 中必须包含 prefix 字段,例如 prefix: /opt/conda/envs/test-env
  2. prefix 目录下必须真实存在对应的 <package>.json 文件(即该目录应为一个真实的 Conda 环境目录)。

environment-with-licenses.yaml 测试样例恰好演示了这种场景:它同时声明了 prefix: testdata,测试数据目录 testdata/conda-meta/ 下预置了对应的包 JSON 文件。若找不到许可证文件,分析器会输出一条 Debug 级日志,提示“License not found”,并附上文档位置供排障(见 environment.go)。

要得到“带 prefix 字段且 conda-meta 目录完备”的 environment.yml,最可靠的方式仍是执行 conda env export 命令导出。

实际操作流程

综合以上机制,推荐按以下流程对 Conda 环境进行扫描:

  1. 导出确定版本的环境描述(若手头只有可读版的 environment.yml):

    conda env export > environment.yml
    

    这能同时保证 SBOM 版本与 License 信息完整。

  2. 扫描本地目录(Trivy 的 filesystem 模式会自动识别 environment.ymlconda-meta/*.json):

    trivy fs --scanners license ./
    

    扫描结果可在 jsontablecyclonedxspdx 等格式间切换,例如输出 SBOM:

    trivy fs --format cyclonedx --output conda-sbom.cdx.json ./
    
  3. 校验结果:核对报告中是否出现预期的包名、精确版本(对 Conda 依赖)与许可证;若发现缺失版本,回头检查 dependencies 中是否仍存在版本范围或通配写法。

关于各类扫描器(vuln / license / secret / misconfig 等)的启用方式、依赖图(Origins)展示与检测优先级等通用行为,可参阅 reporting.mdvulnerability.md

常见问题速查

  • 为什么扫描 environment.yml 时部分包没有版本号? 因为这些依赖使用了版本范围、通配符或多候选写法(如 >13.2.0,<=13.32.40.*13.2|13.3),Trivy 无法确定精确版本。解决方案是先用 conda env export 固定版本。
  • 为什么 License 扫描没有输出?environment.yml 场景,请确认文件中存在 prefix 字段,且该目录下存在 conda-meta/<包名>-<版本>-*.json 元数据。更稳妥的做法是直接扫描 conda env export 导出的环境目录本身(其中包含完整的 conda-meta)。
  • yamlyml 扩展名是否都能识别? 都能。Trivy 的 environment/ 分析器对文件名 environment.yamlenvironment.yml 一视同仁。
  • Trivy 能否报告 Conda 包的漏洞? 当前版本不行。Conda 在漏洞(Vulnerability)扫描器下标记为不支持,仅支持 SBOM 与 License 两类能力。
  • 分析器是否会误伤同名 JSON? 不会。conda-meta 元数据分析器要求文件路径匹配 .*/envs/.+/conda-meta/.+-.+-.+\.json,只有位于 Conda 环境 envs 目录下的三段式包元数据才会被当作 Conda 包处理。

参考实现与测试索引

想要深入了解或自行验证上述行为的读者,可在仓库中查阅以下位置:

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
898
5.82 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
921
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.8 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
596
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
519
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
391