ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Trivy 许可证扫描(License Scanning)完整指南:分类体系、全量扫描与自定义配置

Trivy 许可证扫描(License Scanning)完整指南:分类体系、全量扫描与自定义配置 Trivy 许可证扫描License Scanning完整指南分类体系、全量扫描与自定义配置【免费下载链接】trivyFind vulnerabilities, misconfigurations, secrets, SBOM in containers, Kubernetes, code repositories, clouds and more项目地址: https://gitcode.com/GitHub_Trending/tr/trivyTrivy 的许可证扫描License Scanning能力会检查容器镜像中的许可证文件与包许可证并基于 Google License Classification 提供一套有观点opinionated的风险分类。本文以 docs/guide/scanner/license.md 为骨架结合仓库源码标志定义、分类器实现、文件分析器深入讲解许可证如何被分类为 Forbidden / Restricted 等 7 类并映射为严重级别、标准扫描与--license-full全量扫描的区别、以及--ignored-licenses、--license-confidence-level、自定义分类、文本许可证正则等全套配置方法。读完本文你将能够独立完成镜像与文件系统的许可证合规扫描并按团队合规策略定制分类规则。许可证扫描是什么Trivy 会扫描任意容器镜像中的许可证文件并对许可证关联的风险给出意见化视图。许可证由Google License ClassificationGoogle 开源项目维护的第三方许可证分类标准分为以下 7 类分类Classification含义Forbidden禁止使用Restricted限制使用如强制开源分发Reciprocal互惠修改后需开源Notice需保留版权声明Permissive宽松许可Unencumbered无负担可任意使用Unknown无法识别提示Trivy 无法识别的许可证会被归类为UNKNOWN。由于这些许可证可能违反合规要求官方建议连同未知许可证一并检查。从源码看这 7 个分类在 pkg/fanal/types/license.go 中被定义为LicenseCategory常量forbidden、restricted、reciprocal、notice、permissive、unencumbered、unknown贯穿扫描、分类与报告的整个链路。默认扫描与全量扫描默认标准扫描只扫描由apk、apt-get、dnf、npm、pip、gem等包管理器安装的包的许可证覆盖范围见 docs/guide/coverage/index.md。全量扫描--license-full在包许可证之外还会扫描源码文件、Markdown 文档、文本文件以及LICENSE文档以识别镜像或文件系统内的许可证使用情况。扫描模式支持矩阵License scanningImageRootfsFilesystemRepositorySBOMStandard✅✅✅12✅12✅Full (--license-full)✅✅✅✅-注意全量许可证扫描开销较大耗时较长官方在文档中明确提示这一点。分类到严重级别的映射许可证检查会将识别出的许可证分类并映射到对应的严重级别Severity分类Classification严重级别SeverityForbiddenCRITICALRestrictedHIGHReciprocalMEDIUMNoticeLOWPermissiveLOWUnencumberedLOWUnknownUNKNOWN该映射的源码实现在 pkg/licensing/scanner.go 的categoryToSeverity函数中func categoryToSeverity(category types.LicenseCategory) dbTypes.Severity { switch category { case types.CategoryForbidden: return dbTypes.SeverityCritical case types.CategoryRestricted: return dbTypes.SeverityHigh case types.CategoryReciprocal: return dbTypes.SeverityMedium case types.CategoryNotice, types.CategoryPermissive, types.CategoryUnencumbered: return dbTypes.SeverityLow } return dbTypes.SeverityUnknown }需要说明的是源码实现将 Forbidden 映射为 CRITICAL、Restricted 映射为 HIGH、Reciprocal 映射为 MEDIUM、Notice/Permissive/Unencumbered 统一映射为 LOW与文档表格完全一致。快速开始本节演示如何扫描容器镜像与文件系统中的许可证。标准扫描使用--scanners license指定镜像名称即可$ trivy image --scanners license --severity UNKNOWN,HIGH,CRITICAL alpine:3.15 2022-07-13T17:28:39.5260300 INFO License scanning is enabled OS Packages (license) Total: 6 (UNKNOWN: 0, HIGH: 6, CRITICAL: 0) ┌───────────────────┬─────────┬────────────────┬──────────┐ │ Package │ License │ Classification │ Severity │ ├───────────────────┼─────────┼────────────────┼──────────┤ │ alpine-baselayout │ GPL-2.0 │ Restricted │ HIGH │ ├───────────────────┤ │ │ │ │ apk-tools │ │ │ │ ├───────────────────┤ │ │ │ │ busybox │ │ │ │ ├───────────────────┤ │ │ │ │ musl-utils │ │ │ │ ├───────────────────┤ │ │ │ │ scanelf │ │ │ │ ├───────────────────┤ │ │ │ │ ssl_client │ │ │ │ └───────────────────┴─────────┴────────────────┴──────────┘如示例所示Alpine 3.15 的 6 个 OS 包全部使用 GPL-2.0被分类为 RestrictedHIGH这是 GPL 系许可证在默认分类下的典型结果。默认分类列表中 GPL-2.0 / GPL-3.0 等属于 Restricted 类别见 pkg/licensing/expression/category.go。全量扫描指定--license-full开启全量扫描$ trivy image --scanners license --severity UNKNOWN,HIGH,CRITICAL --license-full grafana/grafana 2022-07-13T17:48:40.9050300 INFO Full license scanning is enabled OS Packages (license) Total: 20 (UNKNOWN: 9, HIGH: 11, CRITICAL: 0) ┌───────────────────┬───────────────────┬────────────────┬──────────┐ │ Package │ License │ Classification │ Severity │ ├───────────────────┼───────────────────┼────────────────┼──────────┤ │ alpine-baselayout │ GPL-2.0 │ Restricted │ HIGH │ ├───────────────────┤ │ │ │ │ apk-tools │ │ │ │ ├───────────────────┼───────────────────┼────────────────┼──────────┤ │ bash │ GPL-3.0 │ │ │ ├───────────────────┼───────────────────┼────────────────┼──────────┤ │ keyutils-libs │ GPL-2.0 │ Restricted │ HIGH │ │ ├───────────────────┼────────────────┼──────────┤ │ │ LGPL-2.0-or-later │ Non Standard │ UNKNOWN │ ├───────────────────┼───────────────────┤ │ │ │ libaio │ LGPL-2.1-or-later │ │ │ ├───────────────────┼───────────────────┼────────────────┼──────────┤ │ libcom_err │ GPL-2.0 │ Restricted │ HIGH │ │ ├───────────────────┼────────────────┼──────────┤ │ │ LGPL-2.0-or-later │ Non Standard │ UNKNOWN │ ├───────────────────┼───────────────────┼────────────────┼──────────┤ │ tzdata │ Public-Domain │ Non Standard │ UNKNOWN │ └───────────────────┴───────────────────┴────────────────┴──────────┘ Loose File License(s) (license) Total: 6 (UNKNOWN: 4, HIGH: 0, CRITICAL: 2) ┌────────────────┬──────────┬──────────────┬──────────────────────────────────────────────────────────────┐ │ Classification │ Severity │ License │ File Location │ ├────────────────┼──────────┼──────────────┼──────────────────────────────────────────────────────────────┤ │ Forbidden │ CRITICAL │ AGPL-3.0 │ /usr/share/grafana/LICENSE │ │ │ │ │ │ │ │ │ │ │ ├────────────────┼──────────┼──────────────┼──────────────────────────────────────────────────────────────┤ │ Non Standard │ UNKNOWN │ BSD-0-Clause │ /usr/share/grafana/public/build/5069.d6aae9dd11d49c741a80.j- │ │ │ │ │ s.LICENSE.txt │ │ │ │ ├──────────────────────────────────────────────────────────────┤ │ │ │ │ /usr/share/grafana/public/build/6444.d6aae9dd11d49c741a80.j- │ │ │ │ │ s.LICENSE.txt │ │ │ │ ├──────────────────────────────────────────────────────────────┤ │ │ │ │ /usr/share/grafana/public/build/7889.d6aae9dd11d49c741a80.j- │ │ │ │ │ s.LICENSE.txt │ │ │ │ ├──────────────────────────────────────────────────────────────┤ │ │ │ │ /usr/share/grafana/public/build/canvasPanel.d6aae9dd11d49c7- │ │ │ │ │ 41a80.js.LICENSE.txt │ └────────────────┴──────────┴──────────────┴──────────────────────────────────────────────────────────────┘全量扫描的报告中新增了Loose File License(s)区块展示散落在镜像文件系统各处的许可证文件例如前端的*.js.LICENSE.txt及其分类与严重级别。上例中AGPL-3.0被归类为 ForbiddenCRITICAL这与源码中 pkg/licensing/expression/category.go 的ForbiddenLicenses默认列表一致——AGPL-1.0、AGPL-3.0 及全部 CC-BY-NC 系列都被列为禁止。从实现上看--license-full对应标志LicenseFull其定义为 eagerly look for licenses in source code headers and license files见 pkg/flag/license_flags.go即启用后 Trivy 会额外启动文件级许可证分析器。配置项详解Trivy 为许可证扫描提供了一系列配置标志以下逐一说明。忽略指定许可证--ignored-licenses使用--ignored-licenses可以从结果中显式移除已识别的许可证$ trivy image --scanners license --ignored-licenses MPL-2.0,MIT --severity HIGH grafana/grafana:latest 2022-07-13T18:15:28.605Z INFO License scanning is enabled OS Packages (license) Total: 2 (HIGH: 2, CRITICAL: 0) ┌───────────────────┬─────────┬────────────────┬──────────┐ │ Package │ License │ Classification │ Severity │ ├───────────────────┼─────────┼────────────────┼──────────┤ │ alpine-baselayout │ GPL-2.0 │ Restricted │ HIGH │ ├───────────────────┤ │ │ │ │ ssl_client │ │ │ │ └───────────────────┴─────────┴────────────────┴──────────┘在 pkg/flag/license_flags.go 中IgnoredLicenses对应配置名license.ignored即同样可以在trivy.yaml中以license.ignored配置。配置分类器置信度--license-confidence-level--license-confidence-level用于调整分类器的置信度阈值取值范围0.0 ~ 1.0默认 0.9。也就是说默认情况下 Trivy 只保留置信度 ≥ 0.9 的分类结果降低阈值可以识别出置信度更低、但可能正确的许可证。例如以默认置信度对 SPDX 许可证列表文本text目录做全量扫描只能检测出 258 个许可证$ trivy fs --scanners license --license-full path/to/spdx/list/data 2023-04-18T10:05:13.601-0700 INFO Full license scanning is enabled Loose File License(s) (license) Total: 258 (UNKNOWN: 70, LOW: 90, MEDIUM: 18, HIGH: 58, CRITICAL: 22)将置信度调整为 0.8 后可以检测出 282 个许可证$ trivy fs --scanners license --license-full --license-confidence-level 0.8 path/to/spdx/list/data 2023-04-18T10:21:39.637-0700 INFO Full license scanning is enabled Loose File License(s) (license) Total: 282 (UNKNOWN: 81, LOW: 97, MEDIUM: 24, HIGH: 58, CRITICAL: 22)实现层面置信度阈值定义在 pkg/flag/license_flags.go配置名license.confidenceLevel并最终传入 pkg/licensing/classifier.go 的Classify函数——该函数基于 Google 的github.com/google/licenseclassifier/v2对文件内容做匹配只保留match.Confidence confidenceLevel的匹配结果并将匹配类型区分为Header文件头与License许可证文件。自定义分类--generate-default-config使用--generate-default-config可以生成默认配置文件然后在其中定制许可证分类。例如若只想禁止 AGPL-3.0可以把它保留在forbidden下而把其他许可证移到别的分类。$ trivy image --generate-default-config $ vim trivy.yaml生成的默认配置结构如下完整内容license: forbidden: - AGPL-3.0 restricted: - AGPL-1.0 - CC-BY-NC-1.0 - CC-BY-NC-2.0 - CC-BY-NC-2.5 - CC-BY-NC-3.0 - CC-BY-NC-4.0 - CC-BY-NC-ND-1.0 - CC-BY-NC-ND-2.0 - CC-BY-NC-ND-2.5 - CC-BY-NC-ND-3.0 - CC-BY-NC-ND-4.0 - CC-BY-NC-SA-1.0 - CC-BY-NC-SA-2.0 - CC-BY-NC-SA-2.5 - CC-BY-NC-SA-3.0 - CC-BY-NC-SA-4.0 - Commons-Clause - Facebook-2-Clause - Facebook-3-Clause - Facebook-Examples - WTFPL - BCL - CC-BY-ND-1.0 - CC-BY-ND-2.0 - CC-BY-ND-2.5 - CC-BY-ND-3.0 - CC-BY-ND-4.0 - CC-BY-SA-1.0 - CC-BY-SA-2.0 - CC-BY-SA-2.5 - CC-BY-SA-3.0 - CC-BY-SA-4.0 - GPL-1.0 - GPL-2.0 - GPL-2.0-with-autoconf-exception - GPL-2.0-with-bison-exception - GPL-2.0-with-classpath-exception - GPL-2.0-with-font-exception - GPL-2.0-with-GCC-exception - GPL-3.0 - GPL-3.0-with-autoconf-exception - GPL-3.0-with-GCC-exception - LGPL-2.0 - LGPL-2.1 - LGPL-3.0 - NPL-1.0 - NPL-1.1 - OSL-1.0 - OSL-1.1 - OSL-2.0 - OSL-2.1 - OSL-3.0 - QPL-1.0 - Sleepycat reciprocal: - APSL-1.0 - APSL-1.1 - APSL-1.2 - APSL-2.0 - CDDL-1.0 - CDDL-1.1 - CPL-1.0 - EPL-1.0 - EPL-2.0 - FreeImage - IPL-1.0 - MPL-1.0 - MPL-1.1 - MPL-2.0 - Ruby notice: - AFL-1.1 - AFL-1.2 - AFL-2.0 - AFL-2.1 - AFL-3.0 - Apache-1.0 - Apache-1.1 - Apache-2.0 - Artistic-1.0-cl8 - Artistic-1.0-Perl - Artistic-1.0 - Artistic-2.0 - BSL-1.0 - BSD-2-Clause-FreeBSD - BSD-2-Clause-NetBSD - BSD-2-Clause - BSD-3-Clause-Attribution - BSD-3-Clause-Clear - BSD-3-Clause-LBNL - BSD-3-Clause - BSD-4-Clause - BSD-4-Clause-UC - BSD-Protection - CC-BY-1.0 - CC-BY-2.0 - CC-BY-2.5 - CC-BY-3.0 - CC-BY-4.0 - FTL - ISC - ImageMagick - Libpng - Lil-1.0 - Linux-OpenIB - LPL-1.02 - LPL-1.0 - MS-PL - MIT - NCSA - OpenSSL - PHP-3.01 - PHP-3.0 - PIL - Python-2.0 - Python-2.0-complete - PostgreSQL - SGI-B-1.0 - SGI-B-1.1 - SGI-B-2.0 - Unicode-DFS-2015 - Unicode-DFS-2016 - Unicode-TOU - UPL-1.0 - W3C-19980720 - W3C-20150513 - W3C - X11 - Xnet - Zend-2.0 - zlib-acknowledgement - Zlib - ZPL-1.1 - ZPL-2.0 - ZPL-2.1 unencumbered: - CC0-1.0 - Unlicense - 0BSD permissive: []这套默认分类清单正是由源码中的各分类默认列表生成的LicenseForbidden、LicenseRestricted、LicenseReciprocal、LicenseNotice、LicensePermissive、LicenseUnencumbered分别对应配置项license.forbidden、license.restricted、license.reciprocal、license.notice、license.permissive、license.unencumbered其默认值直接取自 pkg/licensing/expression/category.go 中移植自 Google licenseclassifier 的ForbiddenLicenses、RestrictedLicenses、ReciprocalLicenses、NoticeLicenses、PermissiveLicenses、UnencumberedLicenses列表见 pkg/flag/license_flags.go。文本许可证Text licenses默认情况下若 Trivy 无法从许可证文本中确定许可证名称会将其归类为 UNKNOWN。要为文本许可证定义分类需要在许可证分类中加入带text://前缀的条目。例如license: forbidden: - text://Text of Apache Software Foundation License由于文本许可证可能很长Trivy 支持在分类中使用正则表达式license: forbidden: - text://.* Apache Software .*注意regex仅用于文本许可证不能用来配置许可证 ID。从源码看text://前缀即LicenseTextPrefix其匹配逻辑实现在 pkg/licensing/scanner.go 的ScanTextLicense函数中遍历各分类下带text://前缀的条目将其余部分作为正则表达式与许可证文本匹配命中即返回对应分类与严重级别同时源码注释指出匹配失败会记录 Debug 日志并继续最终未命中任何模式时返回 UNKNOWN。只启用部分包类型--pkg-types如果你只想扫描某些包类型可以通过--pkg-types传入逗号分隔的包类型列表。可选值os扫描由 OS 包管理器如dpkg、yum、apk管理的 OS 包library扫描语言特定包如由pip、npm、gem安装的包。$ trivy image --pkg-types os ruby:2.4.0该标志同时作用于其他扫描器用于从源头控制纳入分析的包类型范围从而缩小扫描面、提升扫描速度。源码级的实现原理文件级许可证分析器全量扫描依赖文件级许可证分析器 pkg/fanal/analyzer/licensing/license.go其关键行为包括跳过的目录node_modules/由 node 扫描负责、usr/share/doc/由 dpkg 负责等目录会被启发式跳过避免重复扫描见 license.go。接受的扩展名.c、.h、.java、.js、.md、.py、.php、.rb、.sh、.txt、.ts等源码/文本扩展名会被纳入扫描见 license.go。许可证文件名文件名为LICENSE、LICENCE、COPYRIGHT大小写不敏感的文件始终会被检查classifier.go 中定义的LicenseFileNames。可读性预检isHumanReadable会读取文件头部 300 字节通过二进制控制字符检测排除非文本文件见 license.go。置信度注入分析器通过AnalyzerOptions.LicenseScannerOption.ClassifierConfidenceLevel拿到--license-confidence-level的值并用于分类见 license.go。复合许可证表达式的分类判定当包声明的是复合许可证表达式例如(MIT OR GPL-2.0)时pkg/licensing/scanner.go 的detectCategory会递归解析表达式简单表达式直接取该许可证所属分类AND运算符取两侧分类中严重级别更高的一类OR运算符取两侧分类中严重级别更低的一类任一侧为 UNKNOWN整体判定为 UNKNOWNWITH运算符如GPL-2.0 WITH Classpath-exception按简单表达式处理。该判定逻辑会在报告生成前将LicenseFinding的分类与严重级别写入结果见 pkg/fanal/types/license.go。使用建议与注意事项全量扫描--license-full耗时较长建议在 CI 的定时任务或发布前检查中开启日常快速扫描可仅使用标准模式。许可证的合规判定具有强业务属性默认分类来自 Google License Classification团队应结合自身法务口径通过trivy.yaml的license.*配置或--ignored-licenses定制规则。对 UNKNOWN 分类的结果不要直接放过——它们可能是新的、非常见许可证也可能包含潜在违规风险降低--license-confidence-level能帮助识别更多边缘许可证但同时可能引入误报需要结合置信度列综合判断。许可证扫描结果与 OS 包、语言包检测深度绑定若镜像中缺少包管理器的元数据如精简过的 distroless 镜像标准扫描可能无法识别包许可证此时可结合全量文件扫描兜底。总结Trivy 的许可证扫描覆盖从包许可证快速检查到全量文件级许可证识别的完整链路并通过 Google License Classification 提供统一的风险分类与严重级别映射。结合--ignored-licenses、--license-confidence-level、--pkg-types以及基于--generate-default-config的自定义分类含文本许可证正则你完全可以将许可证合规检查标准化为可复用的 CI 流程持续管控镜像与代码仓库中的许可证风险。支持的语言文件清单见 docs/guide/coverage/language/index.md。↩ ↩部分锁文件需要额外文件例如缓存目录中的文件才能检测许可证详见 docs/guide/coverage/index.md。↩ ↩【免费下载链接】trivyFind vulnerabilities, misconfigurations, secrets, SBOM in containers, Kubernetes, code repositories, clouds and more项目地址: https://gitcode.com/GitHub_Trending/tr/trivy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表