安全性审核简介
NuGet 等包管理器的安全审核是一个过程,涉及分析软件项目中所包含包的安全性。 具体包括识别漏洞、评估风险,并提出建议以提高安全性。 审核可以包括对包本身、任何依赖项及其关联风险的审查。 审核的目标是识别和减少攻击者可能利用的任何安全漏洞,例如代码注入或跨站点脚本攻击。
我们还有一篇博客文章,其中讨论了在发现项目要使用的具有已知漏洞的包时采取操作的建议方法,以及帮助获取详细信息的工具。
功能可用性
| NuGet | .NET SDK | Visual Studio | 功能 |
|---|---|---|---|
| 5.9 | .NET 5 SDK (5.0.200) | 空值 | dotnet list package --vulnerable |
| 6.8 | .NET 8 SDK (8.0.100) | Visual Studio 2022 17.8 | PackageReference 的 NuGetAudit |
| 6.10 | 空值 | Visual Studio 2022 17.10 | packages.config 的 NuGetAudit |
| 6.11 | .NET 8 SDK (8.0.400) | Visual Studio 2022 17.11 | PackageReference 的 NuGetAuditSuppress |
| 6.12 | .NET 9 SDK (9.0.100) | Visual Studio 2022 17.12 | 审核源。 packages.config 的 NuGetAuditSuppress。 |
| 7.0 | .NET 10 SDK (10.0.100) | Visual Studio 2026 |
NuGetAuditMode 的默认更改适用于 .NET 10。 dotnet package update --vulnerable |
使用 restore 运行安全审核
restore 命令会在执行常见包操作时自动运行,如首次加载项目、添加新包、更新包版本或删除收藏 IDE 中项目的包。
根据审核源提供的已知漏洞列表检查依赖项。
- 在命令行中,导航到项目或解决方案目录。
- 使用首选工具(例如 dotnet、MSBuild、NuGet.exe、VisualStudio 等)运行
restore。 - 查看警告并解决已知的安全漏洞。
配置 NuGet 审核
审核可以通过 .csproj 中的 MSBuild 属性进行配置,也可以通过作为项目一部分评估的 MSBuild 文件进行配置。
建议在存储库级别配置审核。
| MSBuild 属性 | 默认 | 可能的值 | 备注 |
|---|---|---|---|
| NuGet审计模式 | 请参见下方的 1 |
direct 和 all |
如果只想审核顶级依赖项,可以将该值 direct设置为 。 NuGetAuditMode 不适用于 packages.config 项目。 |
| NuGet审计级别 | 低 |
low、moderate、high 和 critical |
要报告的最低严重性级别。 如果想要查看 moderate、high 和 critical 公告(不包括 low),请将值设置为 moderate |
| NuGetAudit | 是 |
true 和 false |
如果不希望收到安全审核报告,则可以通过将值设置为 false 来完全退出体验 |
-
NuGetAuditMode默认为all当项目的目标是net10.0或更高版本时。 否则NuGetAuditMode,默认为direct. 当项目多目标时,如果有一个目标框架选择all,则审核会将此值用于所有目标框架。
审核源
还原会下载服务器的 VulnerabilityInfo 资源,以检查每个项目正在使用的包列表。
源列表由 NuGet.Config 中的 auditSources 元素定义,如果任何审核源未提供任何漏洞信息,则会引发警告 NU1905。
如果未定义 auditSources 或未添加任何源就将其清除,则将使用 packageSources 并抑制警告 NU1905。
由于包替换攻击的常见缓解措施是使用来自 nuget.org 上游的单个包源,因此 NuGet 不会配置为使用 nuget.org 作为包源,因此可以使用审核源来使用 nuget.org(或任何其他提供漏洞信息的源),而不将其用作包源。
nuget.org 漏洞数据库的数据源是 GitHub 顾问数据库。 请注意,V2 协议已弃用,因此,如果 nuget.config 仍在使用 V2 终结点,则必须迁移到 V3 终结点。
<configuration>
<auditSources>
<clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
</auditSources>
</configuration>
注意:下表列出了支持审核源的功能。
| 引入 | 支持审核源的功能 |
|---|---|
| NuGet 6.12、.NET 9.0.100 SDK 和 Visual Studio 2022 17.12 | Restore |
| NuGet 6.14、.NET 9.0.300 SDK | dotnet package list --vulnerable |
| 尚不支持 | Visual Studio 包管理器 UI 中的 NuGet AuditSources 支持 |
排除公告
可以选择通过为每个公告添加一个新的 NuGetAuditSuppress MSBuild 项,在审核报告中排除特定的公告。
定义一个 NuGetAuditSuppress 项,其中的 Include= 元数据设定为希望抑制的公告 URL。
<ItemGroup>
<NuGetAuditSuppress Include="https://github.com/advisories/XXXX" />
</ItemGroup>
与其他 NuGet 审核配置属性类似,NuGetAuditSuppress 项可以在项目或仓库级别定义。
自 NuGetAuditSuppress 起,PackageReference 项目可以使用 。
它适用于具有 Visual Studio 17.12 和 NuGet 6.12 的 packages.config。
警告代码
| 警告代码 | 原因 |
|---|---|
| NU1900 | 与包源通信时出错,同时获取漏洞信息。 |
| NU1901 | 检测到低严重性的包 |
| NU1902 | 检测到中严重性的包 |
| NU1903 | 检测到高严重性的包 |
| NU1904 | 检测到严重严重性的包 |
| NU1905 | 审核源不提供漏洞数据库 |
可以自定义生成,将这些警告视为错误,将警告视为错误,或将警告视为错误。
例如,如果已用于 <TreatWarningsAsErrors> 将所有(C#、NuGet、MSBuild 等)警告视为错误,则可以用于 <WarningsNotAsErrors>$(WarningsNotAsErrors);NU1901;NU1902;NU1903;NU1904</WarningsNotAsErrors> 防止将来发现的漏洞破坏生成。
或者,如果要将低漏洞和中等漏洞保留为警告,但将高漏洞和严重漏洞视为错误,并且未使用 TreatWarningsAsErrors,则可以使用 <WarningsAsErrors>$(WarningsAsErrors);NU1903;NU1904</WarningsAsErrors>。
注意
packages.config 项目不支持消息严重性的 MSBuild 属性(如 NoWarn 和 TreatWarningsAsErrors)。
在 CI 中运行 NuGet 审核
使用专用审核管道将错误与警告分离
可以使用 MSBuild 的条件语句为运行审核配置专用 CI 管道,而无需将审核警告视为其他管道或本地生成中的错误。 根据您的 CI 系统和团队流程,失败的审核管道运行可以触发向团队发送电子邮件,并且可以在仪表板上显示管道最近一次运行状态的徽章。
与编程中的许多内容一样,有多种方法可以实现结果。 一个选项是仅将 NuGet 审核警告视为审核管道中的错误。
<PropertyGroup>
<NuGetAuditCodes>NU1900;NU1901;NU1902;NU1903;NU1904;NU1905</NuGetAuditCodes>
<WarningsAsErrors Condition=" '$(AuditPipeline)' == 'true' ">$(WarningsAsErrors);$(NuGetAuditCodes)</WarningsAsErrors>
<WarningsNotAsErrors Condition=" '$(AuditPipeline)' != 'true' ">$(WarningsNotAsErrors);$(NuGetAuditCodes)</WarningsNotAsErrors>
</PropertyGroup>
然后,在管道中运行还原操作,并指定条件所使用的属性。 例如,使用 GitHub Actions 语法:
- name: Restore with NuGet Auditing
run: dotnet restore -p:AuditPipeline=true
属性名称 AuditPipeline 只是一个示例,只要 MSBuild 条件和命令行中的名称相同,就可以根据需要对其进行自定义。
MSBuild 在读取尚未定义的属性时也使用环境变量,因此环境变量是命令行参数的替代方法。
通过利用条件有选择地使 NuGet 审核警告导致还原失败,您可以设立一个专门的管道来检查包中的已知漏洞,同时避免新的安全公告在不凑巧的时间阻碍 bug 修复。 启用本地构建的 NuGet 审核警告,使开发人员能够收到有关新安全公告的非阻塞通知,并可鼓励他们通过升级包版本来更快修复漏洞,而不是等待某人检查审核管道的状态。
确保恢复审核的项目
在 MSBuild 17.13 和 .NET 9.0.200 中,NuGet 在还原任务中新增了输出属性 RestoreProjectCount、RestoreSkippedCount 和 RestoreProjectsAuditedCount。
这可用于确保在还原过程中审计运行。
请注意,这些输出属性在 静态图形还原中不可用。
由于 MSBuild 是一种脚本语言,因此可以实现多种不同的方法,但也具有与 MSBuild 相同的限制。 一个示例是,在解决方案文件所在的同一目录中创建文件 Directory.Solution.targets ,其内容具有类似于以下内容的目标。 请注意, Directory.Build.props 通常用于,但由项目导入。 但是,NuGet 的还原目标和任务在解决方案级别运行,因此需要位于 MSBuild 的解决方案扩展性文件中,而不是项目/生成文件。
<Project>
<Target Name="AssertRestoreTaskOutputProperties"
AfterTargets="Restore"
Condition="'$(CI)' == 'true'">
<Error
Condition="'$(RestoreProjectsAuditedCount)' != '$(RestoreProjectCount)'"
Text=""Restore did not audit every project in the solution. Expected: $(RestoreProjectCount) Found: $(RestoreProjectsAuditedCount)"" />
</Target>
</Project>
根据您的用例,您可能希望在错误消息上使用条件 '$(RestoreProjectCount)' != '$([MSBuild::Add($(RestoreProjectsAuditedCount), $(RestoreSkippedCount))' ,以处理那些因为已是最新而被跳过还原的项目。
同样,请考虑是否希望此错误在所有地方发生,还是仅在 CI 管道中发生,以及在 CI 环境中定义了哪些环境变量,并将其纳入目标条件中。
请再次注意,由于 MSBuild 是一种脚本语言,您可以利用其任何功能来随心所欲地自定义代码库。
查看 MSBuild 的元项目 和 binlog文件 有助于开发和排查解决方案级别的目标问题。
dotnet list package --vulnerable
成功还原项目后,dotnet list package 具有一个 --vulnerable 参数,可根据哪些包具有已知漏洞筛选包。
请注意, --include-transitive 这不是默认值,因此应包含。
报告存在已知漏洞的包时的操作
我们还有一篇博客文章,其中讨论了在发现项目要使用的具有已知漏洞的包时采取操作的建议方法,以及帮助获取详细信息的工具。
更新后发现的安全漏洞
如果发现安全漏洞并且更新可用于包,则可以:
- 使用包含安全修补程序的较新版本编辑
.csproj或其他包版本位置 (Directory.Packages.props)。 - 使用 Visual Studio 中的 NuGet 包管理器用户界面更新单个包。
- 运行该命令,
dotnet package update --vulnerable将项目中所有易受攻击的包更新到第一个版本,且没有已知漏洞。 - 运行
dotnet package update或dotnet package add命令,具有相应的包 ID,以更新至最新版本。 在使用 .NET 9 或更早版本时,请使用dotnet add package。
可传递包
如果顶级包的可传递依赖项中存在已知漏洞,则可以使用以下选项:
- 将固定包版本添加为直接包引用。 注意: 在新包版本更新可用时,请务必删除此引用,并确保维护预期行为的已定义属性。
- 将 中央包管理与可传递固定功能配合使用。
- 取消通知,直到可以解决该通知 。
- 在顶级包跟踪器中提出问题以请求更新。
发现安全漏洞但未更新
如果包中存在已知漏洞且没有安全修补程序,可以执行以下操作。
- 检查顾问报告中概述的任何缓解因素。
- 如果包标记为已弃用或放弃,请使用建议的包。
- 如果包为开放源代码,请考虑提供修补程序。
- 在包的问题跟踪器中打开问题。
检查缓解因素
查看安全顾问,了解可能允许你继续使用包含漏洞的包的任何缓解因素。 仅当在特定框架、操作系统或调用特殊函数上使用代码时,该漏洞才存在。
使用建议的包
如果针对正在使用的包报告了安全公告,并且包被标记为已弃用或似乎被放弃,请考虑使用包作者声明的任何建议备用包,或者包含维护的类似功能的包。
参与修复
如果安全公告不存在修补程序,建议对包的开放源代码存储库拉取请求中的漏洞进行更改,或者通过 NuGet.org 包详细信息页上 Contact owners 的部分联系作者。
打开问题
如果不想修复漏洞或无法更新或替换包,请在包的问题跟踪器或首选联系人方法中打开问题。
在 NuGet.org 上,你可以导航到包详细信息页,然后单击 Report package,这将引导你与作者取得联系。
未找到安全漏洞
如果未发现任何安全漏洞,这意味着在检查的当前时刻,包图中找不到具有已知漏洞的包。
由于随时可以更新咨询数据库,因此我们建议定期检查 dotnet restore 输出并确保在持续集成过程中相同。
总结
安全审核功能对于维护软件项目的安全性和完整性至关重要。 这些功能提供针对安全漏洞的附加保护层,并确保你可以放心地使用开放源代码包。