news 2026/9/10 1:29:04

Trivy .NET 与 NuGet 依赖扫描完全指南:支持矩阵、文件解析原理与 License 检测机制

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Trivy .NET 与 NuGet 依赖扫描完全指南:支持矩阵、文件解析原理与 License 检测机制

Trivy .NET 与 NuGet 依赖扫描完全指南:支持矩阵、文件解析原理与 License 检测机制

【免费下载链接】trivyFind vulnerabilities, misconfigurations, secrets, SBOM in containers, Kubernetes, code repositories, clouds and more项目地址: https://gitcode.com/GitHub_Trending/tr/trivy

导读:本文围绕 Trivy 对 .NET 生态(.NET CoreNuGet)的依赖扫描能力展开,系统梳理受支持的四种清单文件(*.deps.jsonpackages.config*Packages.propspackages.lock.json)的能力边界,并结合仓库源码揭示其解析、依赖图构建与 License 检测的底层实现。读完本文,你将能准确判断在镜像、根文件系统、文件系统与 Git 仓库四种扫描目标下应选用哪种 .NET 清单文件,理解 transitive/dev 依赖与溯源能力的差异,并掌握 NuGet 软件许可识别的前提条件与局限。

一、支持范围总览:.NET CoreNuGet两类组件

根据 dotnet.md,Trivy 对 .NET 生态的支持分为两类组件(Artifact):

ArtifactSBOMVulnerabilityLicense
.NET Core-
NuGet

也就是说:

  • .NET Core(对应*.deps.json)只产出 SBOM 与漏洞结果,不参与 License 扫描;
  • NuGet(对应packages.config*Packages.propspackages.lock.json)三种结果均支持,其中软件许可识别依赖下文所述的 nuspec 机制。

这与 docs/guide/coverage/language/index.md 中列出的语言矩阵一致:.NET族的四种清单文件(packages.lock.jsonpackages.config.deps.json*Packages.props)在镜像(Image)、根文件系统(Rootfs)、文件系统(Filesystem)与 Git 仓库(Repository)四种扫描模式下均为开启状态,且这些文件的具体路径不影响识别——Trivy 依赖内容与约定文件名进行匹配。

二、能力矩阵:按清单文件逐项对照

Trivy 对不同清单文件的解析深度差异显著,原文档给出的能力矩阵是选择扫描文件时的第一依据:

Package managerFileTransitive dependenciesDev dependenciesDependency graphPosition
.NET Core*.deps.jsonExcluded
NuGetpackages.configExcluded--
NuGet*Packages.props-Excluded--
NuGetpackages.lock.jsonIncluded

解读上表的几个关键维度:

  • Transitive dependencies:能否还原出传递依赖。.deps.jsonpackages.lock.json都完整记录了整棵依赖树,因此支持;packages.config主要记录直接引用(是否含全量传递依赖依赖实际工程还原结果,Trivy 只取其中出现的包名与版本);*Packages.props仅声明项目引用的包与版本,不含传递依赖。
  • Dev dependencies:开发期依赖是否进入报告。.deps.jsonpackages.config*Packages.props中的开发期依赖均被排除;只有packages.lock.json会包含。
  • Dependency graph 与 Position:这两列决定报告能否展示依赖关系图与“漏洞来自哪一层/哪个位置”的溯源能力。仅.deps.jsonpackages.lock.json同时具备,可结合--show-origins溯源(详见 reporting.md)。

下面逐文件深入解析。

三、*.deps.json:.NET Core 应用运行时依赖的唯一来源

3.1 行为约定

Trivy 解析*.deps.json.NET Core应用在dotnet build/publish时生成的项目依赖清单),并只把运行时依赖纳入报告

Trivy only includes runtime dependencies in the report.

开发期(dev)依赖默认被排除在结果之外。

3.2 源码级解析原理

文件识别由 analyzer 层完成,见 pkg/fanal/analyzer/language/dotnet/deps/deps.go:

  • Required()通过strings.HasSuffix(filePath, ".deps.json")匹配所有.deps.json结尾的文件(deps.go);
  • 匹配后交由 core_deps 解析器 处理。

真正完成“依赖还原”的核心在 parse.go 中,它主要读取 JSON 中的三块结构(见结构体定义 parse.go):

  • libraries:全部包库清单(每个条目形如name/version);
  • runtimeTarget:当前运行时目标名;
  • targets:按运行时目标组织的依赖图,每个库记录其dependenciesruntimeruntimeTargetsnative等区段。

解析流程大致分两轮:

  1. 收集包(collectPackages):遍历libraries,跳过非package/project/runtimepack类型的库;对type: project的条目通过“是否被其他库引用”识别出唯一的根项目,并标记RelationshipRoot(工作区中的其它项目标记为RelationshipWorkspace),见 rootProject。
  2. 构建依赖图(buildDependencyGraph):依据targets段的引用关系,为每个包计算其DependsOn列表,并把根项目的直接依赖标记为RelationshipDirect、其余传递依赖标记为RelationshipIndirect,见 parse.go。

这解释了上表中.deps.jsonDependency graph ✓Position ✓:解析器会生成ftypes.Dependency{ID, DependsOn}结构并记录包在文件中的Location,为后续依赖溯源报告提供数据。

3.3 值得注意的实现细节

  • targets中找不到runtimeTarget.Name对应的目标时,Trivy 会回退为把libraries中的全部依赖纳入报告(但不再构建依赖关系),对应代码注释见 parse.go。
  • 若存在可用的targets,则会通过isRuntimeLibrary过滤掉非运行时库(只保留含runtime/runtimeTargets/native区段的条目),确保“仅运行时依赖”的语义,见 parse.go。
  • 针对自包含(self-contained)发布,.NET SDK 会在libraries中为内置运行时添加合成前缀runtimepack.(例如runtimepack.Microsoft.NETCore.App.Runtime.linux-x64)。解析器会剥离该前缀,使运行时包与框架依赖型应用报告出同名条目,见 parse.go 与 packageID。
  • 该解析器覆盖了多项目、自包含、缺失 target、无 libraries 等边界情形,测试数据见 core_deps/testdata(含multi-project.deps.jsonself-contained.deps.jsonmissing-target.deps.json等)。

四、packages.config:仅提供包名与版本

4.1 行为约定

对于经典packages.config(非 SDK 风格项目),Trivy只从文件中提取依赖的名称与版本,不还原依赖树、也不提供位置信息。若要获得依赖关系图,官方建议改用packages.lock.json

4.2 典型文件形态

仓库测试数据(nuget/testdata/config/packages.config)展示的正是这类文件的典型形态:

<?xml version="1.0" encoding="utf-8"?> <packages> <package id="Microsoft.AspNet.WebApi" version="5.2.2" targetFramework="net45" /> <package id="Newtonsoft.Json" version="6.0.4" targetFramework="net45" /> </packages>

解析时,NuGet analyzer 只抽取每个<package>idversion属性——对应上表中Dependency graph: -Position: -的结果。

五、*Packages.props:解析 MSBuild 包版本声明

Trivy 支持解析*Packages.props文件,且同时兼容两种形态

  • 传统Packages.props
  • 现代集中式包管理使用的Directory.Packages.props(MSBuild 中央包版本声明)。

这一类文件本质是 MSBuild 属性/条目定义,声明了项目引用的包及其版本,因此:

  • 不含传递依赖(Transitive:-);
  • 开发期依赖被排除(Dev: Excluded);
  • 不产出依赖图与位置信息。

在实现层面,该能力由一个独立的 analyzer 负责,见 pkg/fanal/analyzer/language/dotnet/packagesprops/packagesprops.go:

  • Required()对文件名字段做大小写不敏感packages.props后缀匹配(源码注释特别说明 NuGet 对全小写文件名同样正常工作),见 packagesprops.go;
  • 具体解析逻辑位于 pkg/dependency/parser/nuget/packagesprops,其测试数据覆盖了Directory.Packages.props、传统packages.props、空ItemGroup、变量引用等多种形态。

5.1 与 packages.config / lock 文件的协同

需要注意:Trivy 的 NuGet analyzer 是以“应用”为单位并行处理多个文件的。在 nuget.go 的PostAnalyze中,它会遍历扫描目标下所有满足条件的文件,并依据文件名自动切换解析器:packages.lock.json使用 lock 解析器、packages.config使用 config 解析器(默认解析器为 lock),而*Packages.props走独立的 packagesprops analyzer。因此一个仓库中同时出现多种清单文件时,各自解析结果会分别汇总。

六、packages.lock.json:首选的完整依赖与溯源来源

6.1 启用与维护

packages.lock.json需要先在工程中启用锁文件(NuGet 的 PackageReference 工程可通过设置RestorePackagesWithLockFile或执行dotnet restore --use-lock-file生成,官方对此有专门说明)。原文档特别给出两点实操提醒:

  1. 务必在修改依赖后保持锁文件是最新的
  2. 若锁文件过期(依赖声明与解析结果不一致),扫描结果将失真。

6.2 典型文件形态

仓库测试数据(nuget/testdata/lock/packages.lock.json)展示了标准结构:

{ "version": 1, "dependencies": { ".NETCoreApp,Version=v5.0": { "Newtonsoft.Json": { "type": "Direct", "requested": "[12.0.3, )", "resolved": "12.0.3", "contentHash": "6mgjfnRB4jKMlzHSl+VD+oUc1IebOZabkbyWj2RiTgWwYPPuaK1H97G1sHqGwPlS5npiF5Q0OrxN1wni2n5QWg==" }, "NuGet.Frameworks": { "type": "Direct", "requested": "[5.7.0, )", "resolved": "5.7.0", "contentHash": "7Q/wUoB3jCBcq9zoBOBGHFhe78C13jViPmvjvzTwthVV8DAjMfpXnqAYtgwdaRLJMkTXrtdLxfPBIFFhmlsnIQ==", "dependencies": { "Newtonsoft.Json": "12.0.3" } } } } }

可以看到锁文件按目标框架(TFM)分块,每个包带typeDirect/Transitive)、resolved版本、contentHash以及内嵌的dependencies(即该包的传递依赖声明)——这为 Trivy 还原完整依赖树提供了可靠数据。

与之相对,lock 解析器的测试用例还覆盖了旧版(legacy)、多目标框架、含子依赖等多种形态。解析能力同时受packages.lock.json文件本身version字段兼容性约束,扫描时请使用 NuGet 正常生成的锁文件。

6.3 能力优势

  • Transitive ✓:锁文件天然包含传递依赖与解析版本;
  • Dev dependencies: Included:与其它三类文件不同,packages.lock.json会把开发期依赖一并纳入报告(这是四类清单中唯一会包含 dev 依赖的文件);
  • Dependency graph ✓ / Position ✓:为依赖溯源(--show-origins)提供完整输入。

七、License 检测:依赖.nuspec的解析机制

7.1 为什么需要 nuspec

packages.config(以及packages.lock.json)本身不携带软件许可信息,因此 Trivy 转向 NuGet 的“全局包缓存目录”(global packages folder)中查找对应的*.nuspec清单文件来识别许可证。

7.2 支持路径与判定规则

从 nuspec.go 的实现看,机制非常明确:

  • 全局包目录解析:优先读取NUGET_PACKAGES环境变量;若未设置,回退到默认路径($HOME/.nuget/packages)。目前仅支持这两个位置,见 newNuspecParser。
  • 路径拼接:NuGet 缓存目录约定全部小写,解析器会把包名与版本转小写后拼接packagesDir/<name>/<version>/<name>.nuspec(例如Newtonsoft.Json13.0.3 →$HOME/.nuget/packages/newtonsoft.json/13.0.3/newtonsoft.json.nuspec),见 findLicense。
  • 只认 SPDX expression.nuspec<license>元素带有type属性,Trivy 仅接受type="expression"且内容非空的许可表达式;licenseUrl字段已被弃用,Trivy 不会解析它

注意一个易被忽略的边界:.nuspec元数据里用type="file"指向自定义许可证文件(而非表达式)的情形不会得到 License 结果。

7.3 找不到缓存目录时的行为

nuspec解析依赖本机已经restore过的包缓存。若被扫描的环境里不存在NUGET_PACKAGES也没有默认缓存目录,newNuspecParser会构造一个空的 packagesDir,此时 analyzer 输出调试日志 “The nuget packages directory couldn't be found. License search disabled”(见 nuget.go),即License 检测被静默禁用,但包与漏洞扫描不受影响。在 CI 容器里做离线扫描时,需要提前准备全局包缓存或显式设置NUGET_PACKAGES

packages.lock.json的 License 检测机制与packages.config完全一致——同样通过全局包缓存中的 nuspec 进行识别,因此上表对两类文件统一标注 License ✓。

八、实战:选择正确的清单文件与扫描方式

结合 docs/guide/coverage/language/index.md 的能力矩阵与本文前述差异,落地建议如下:

  1. 构建产物/镜像扫描*.deps.json(随发布输出生成)是镜像、Rootfs 场景下 .NET 应用唯一可用的完整依赖来源,应确保发布目录保留该文件;此时 License 维度对.NET Core组件不可用。
  2. 源码/仓库扫描:优先让工程开启并提交packages.lock.json——它同时提供 transitive、dev 依赖、依赖图与位置信息,配合--show-origins(见 docs/guide/configuration/reporting.md)可获得最佳溯源体验。
  3. 没有锁文件的旧工程packages.config*Packages.props仍可兜底,但只能得到直接引用的包名与版本,无法还原依赖图。
  4. License 识别:扫描前确认存在 NuGet 全局包缓存(默认$HOME/.nuget/packagesNUGET_PACKAGES),并确认包的 nuspec 使用license(expression)而非licenseUrl

例如在代码仓库或文件系统上执行:

trivy fs --scanners vuln,license,secret,config ./ trivy repo --scanners vuln,license .

对容器镜像则:

trivy image --scanners vuln,license your-dotnet-app:latest

若想看漏洞对应的依赖出处,追加报告选项:

trivy fs --scanners vuln --show-origins ./

九、小结

Trivy 对 .NET 生态的支持覆盖.NET CoreNuGet两大类组件、四种清单文件,扫描结果横跨 SBOM、漏洞与 License 三个维度。其中*.deps.jsonpackages.lock.json提供最完整的依赖图与位置溯源能力,packages.config*Packages.props只做浅层解析,License 检测则依赖本地 NuGet 全局缓存中的 nuspec 且仅支持 SPDX expression。理解上述能力边界后,你就能针对镜像、根文件系统、文件系统与 Git 仓库等不同目标,选择最合适的清单文件与扫描策略。

继续探索可参见:.NET 相关 analyzer/parser 源码(deps.go、nuget.go、packagesprops.go、core_deps 解析器)及其测试数据(nuget/testdata、core_deps/testdata),以及语言族总览 index.md。

【免费下载链接】trivyFind vulnerabilities, misconfigurations, secrets, SBOM in containers, Kubernetes, code repositories, clouds and more项目地址: https://gitcode.com/GitHub_Trending/tr/trivy

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 1:28:49

嵌入式FFT谐波分析实战:从采样率到THD计算的完整实现

简介&#xff1a;这份资源以C语言实现FFT快速傅里叶变换&#xff0c;可用于电力系统、音频处理与通信领域的谐波分析&#xff0c;能够计算从基波到第51次谐波的含量&#xff0c;帮助评估非线性负载导致的波形失真。压缩包内共3个文件&#xff0c;包括C源码、配套头文件以及一份…

作者头像 李华
网站建设 2026/9/10 1:26:59

Unet系列分割模型对比实践:从Attention到R2U的科学训练

简介&#xff1a;面向计算机视觉与医学图像分析场景的深度学习资源包&#xff0c;提供Unet、AttentionUnet、R2Unet和R2AUet四种经典分割模型的可运行工程&#xff0c;并配有ISIC 2017皮肤病变数据集局部样本&#xff0c;零基础学习者可按照示例快速跑通&#xff0c;中高级研究…

作者头像 李华
网站建设 2026/9/10 1:26:57

c++ bug

报错&#xff1a; “D:\Build\gdal-3.10.2\INSTALL.vcxproj”(默认目标) (1) -> “D:\Build\gdal-3.10.2\ALL_BUILD.vcxproj”(默认目标) (3) -> “D:\Build\gdal-3.10.2\frmts\gif\gdal_GIF.vcxproj”(默认目标) (38) -> (ClCompile 目标) -> F:\Anaconda3\Librar…

作者头像 李华