tess-fun/fleetreach

GitHub: tess-fun/fleetreach

FleetReach 是一款 Rust 编写的群体级依赖安全审计 CLI,一次性扫描多个仓库并对已知漏洞进行去重、排序、爆炸半径分析和批量修复编排。

Stars: 0 | Forks: 0

# fleetreach [![crates.io](https://img.shields.io/crates/v/fleetreach-cli.svg)](https://crates.io/crates/fleetreach-cli) [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/tess-fun/fleetreach/actions/workflows/ci.yml) [![MSRV](https://img.shields.io/badge/MSRV-1.89-blue)](#msrv) [![License](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue)](#license) **一个面向群体的依赖安全审计工具。** 将它一次性指向多个代码仓库, 即可获得一个去重、排序且适配 CI pipeline 的全局视图,了解整个群体中哪些依赖 存在已知的安全公告(以及供应链警告: 未维护、不可靠、通知;甚至包括针对 Rust 工具链 本身的安全公告)。在此之上,你还可以获得爆炸半径分析(即哪一次单独的修复可以清除 最多的仓库,区分直接依赖与间接依赖),一个批量修复队列, 覆盖整个群体的 `--why` 来源追踪、扫描间的漂移追踪,以及 SARIF / JSON / OpenVEX 输出。单一二进制文件:无需运行服务器,无需配置 SBOM pipeline。 它覆盖 12 个生态系统(Rust、Go、npm、PyPI、RubyGems、Packagist、NuGet、Julia、 Swift、Hex、Maven、GitHub Actions),并且对于 Rust,它增加了一种可靠的基于 MIR 的 可达性分析,可以证明存在漏洞的函数是否真正可被调用。 它 **不是** 一个扫描器或安全公告数据库。它是一个基于已审计数据源的编排和 关联层:用于 Rust 的 [`rustsec`](https://crates.io/crates/rustsec) 引擎(与 `cargo-audit` 基于 相同的库构建)以及用于其他所有 生态系统的 [OSV](https://osv.dev) 数据库。其信任边界是“结构化的安全公告数据加上你自己的 配置”,绝不依赖原始 HTML,并且它采用失败即关闭原则:它无法扫描的缺口绝不会 被报告为安全。 ## 横向对比 `fleetreach` 刻意占据了主流扫描器留下的空白领域: 轻量级、CLI 原生、**群体级别** 的审计。 - **对比 `osv-scanner` (Google)、Trivy、Grype。** 这些工具一次扫描一个项目, 并回答“*这个项目* 有漏洞吗?”。`fleetreach` 在一次扫描中处理多个仓库, 并回答群体级别的问题:*哪一次单独的修复可以清除最多的仓库,我该如何安排工作顺序?* (即 `impact` / `blast` / `packages` / `remediation` 视图)。它刻意保持了较小的功能表面积:没有容器或 OS 扫描(请使用 Trivy/Grype 进行此类扫描),也没有自带的安全公告数据库。 - **对比 OWASP Dependency-Track。** 它是资产组合管理领域的传统强者,但它是 一个*需要你自行运维的服务器*:需要搭建平台、导入 CycloneDX SBOM、托管 数据库和 Web UI。`fleetreach` 是一个单一的二进制程序,你可以直接在 CI 或 shell 中针对 `fleet.toml` 运行它。无需服务器,无需 SBOM pipeline,无需托管状态。 - **特别是对于 Rust。** 它增加了一种*可靠的*静态可达性模式(带有见证链的 MIR 调用图分析),这是大多数开源扫描器所缺乏的,并建立在失败即关闭的 CI 契约之上,在此契约下,错误的“安全报告”被视为 最糟糕的输出结果。 如果你需要容器扫描、托管仪表板或单仓库 CI 检查,上述 工具更合适。如果你想要一条命令来回答“我的*群体* 的 依赖风险是什么,我首先该修复什么”,这正是它的用武之地。 ## 安装 ``` cargo install fleetreach-cli --features network # the `fleetreach` binary, with DB fetch + enrichment ``` 默认构建版本是 **纯 Rust**(没有内置的 C 语言 TLS 栈):它不支持网络 功能,需要通过 `--db ` 使用本地的 advisory-db 克隆。可选开启的 `network` feature 增加了 advisory-DB 获取和 KEV/EPSS/NVD 数据丰富化功能(引入 `rustls` TLS 栈)。使用 `--features network` 安装可获得通常的运行时拉取 行为;省略它则获得最精简、依赖少、纯离线(`--db`)的构建。 或者从源码构建: ``` git clone https://github.com/tess-fun/fleetreach cargo install --path crates/cli --features network # omit --features network for the pure-Rust offline build ``` ## 使用方法 ``` fleetreach scan -c fleet.toml # human table (default) fleetreach scan -c fleet.toml -f json # machine payload on stdout, clean for | jq fleetreach scan -c fleet.toml -f sarif # SARIF 2.1.0 for GitHub code scanning fleetreach scan -c fleet.toml -f impact # advisories ranked by repos affected fleetreach scan -c fleet.toml -f blast # blast radius split direct vs transitive fleetreach scan -c fleet.toml -f packages # dependencies ranked by fleet reach fleetreach scan -c fleet.toml -f fix-first # advisories ranked by what to patch first fleetreach scan -c fleet.toml -f remediation # the fix queue: what to bump, batched fleetreach scan -c fleet.toml -f packages-json # the packages rollup as JSON fleetreach scan -c fleet.toml -f remediation-json # the fix queue as JSON fleetreach scan --why serde # how does `serde` get into the tree? fleetreach scan -c fleet.toml --npm-vuln-db file://./npm-osv # also audit npm repos fleetreach scan -c fleet.toml --pypi-vuln-db file://./pypi-osv # also audit Python repos fleetreach scan -c fleet.toml --packagist-vuln-db file://./packagist-osv # also audit PHP/Composer repos fleetreach scan -c fleet.toml --rubygems-vuln-db file://./rubygems-osv # also audit Ruby repos fleetreach scan -c fleet.toml --nuget-vuln-db file://./nuget-osv # also audit .NET/NuGet repos fleetreach scan -c fleet.toml --julia-vuln-db file://./julia-osv # also audit Julia repos fleetreach scan -c fleet.toml --swift-vuln-db file://./swift-osv # also audit Swift repos fleetreach scan -c fleet.toml --hex-vuln-db file://./hex-osv # also audit Elixir/Hex repos fleetreach scan -c fleet.toml --ghactions-vuln-db file://./gha-osv # also audit GitHub Actions pins fleetreach scan -c fleet.toml --maven-vuln-db file://./maven-osv # also audit Java (gradle.lockfile/pom.xml) fleetreach diff old.json new.json # what changed between two scans ``` `impact` 视图通过评估安全公告影响的 crate 数量来排序,回答了群体级别的 问题(*哪一次修复可以清除最多的仓库?*)。以下示例 来自一个包含十个仓库的演示群体(参见 [`examples/demo-fleet.toml`](examples/demo-fleet.toml)): ``` Repos Severity Advisory Affected Title 2 medium 6.2 RUSTSEC-2020-0071 payments-api, scheduler Potential segfault in time 1 critical 9.8 RUSTSEC-2021-0003 ingest-worker SmallVec::insert_many overflow 1 critical 9.8 RUSTSEC-2021-0097 ls-replacement SM2 decryption buffer overflow 1 high 8.6 RUSTSEC-2024-0013 ls-replacement libgit2 memory corruption 1 high 7.5 RUSTSEC-2022-0013 search-svc regex repetition DoS ``` 首行是一个*中等* 级别,而不是严重级别:`time` 段错误是唯一 存在于两个仓库中的安全公告,因此一次升级即可同时修复 `payments-api` 和 `scheduler`。这种排序正是单仓库工具无法回答的问题。 `blast` 视图保持了相同的排序,但将每个安全公告的影响范围拆分为 **直接** 和 **间接** 仓库,并添加了修复路径提示,因为 *如何* 修复取决于这种划分:如果一个公告主要间接影响其所在的仓库,则无法 通过编辑这些仓库的 manifest 来修复(你需要上游升级或依赖 覆盖 → `upstream`),而直接的则可以(`manifest`)。一项针对 真实 Go 生态系统的语料库研究发现,约 3/4 的易受攻击依赖暴露是间接的,因此 单纯受影响仓库的计数会掩盖修复策略。 ``` Repos Direct Transitive Fix Severity Advisory Title 2 1 1 mixed unknown RUSTSEC-2025-0004 ssl select_next_proto UAF 1 1 0 manifest critical 9.8 RUSTSEC-2021-0003 SmallVec::insert_many overflow 1 0 1 upstream medium 6.2 RUSTSEC-2020-0071 Potential segfault in time ``` `packages` 视图将这些行向上汇总了一级 —— 汇总到 *依赖* 本身。一个包通常 在多个仓库中存在许多安全公告,而一次升级即可解决所有问题,因此 这回答了“哪个依赖是我群体中最大的负债?”。它按群体影响范围对易受攻击的 依赖进行排序,带有同样的直接/间接划分,并显示一次升级可以 解决的安全公告数量: ``` Repos Direct Transitive Advisories Severity Fix Package 3 0 3 2 medium upstream time 2 1 1 7 unknown mixed openssl 1 1 0 1 critical manifest smallvec ``` 在这里,一次 `openssl` 升级即可解决七个安全公告 —— 这是按安全公告 划分的视图无法展示的汇总信息。(`-f json` 会在每次出现时携带 `dependency_kind`,并且 SARIF 结果会增加一个 `dependencyKind` 属性,因此 CI 消费者可以获得相同的信号。) `fix-first` 视图回答了互补的问题(*我首先该修复 什么?*)。它以严重性为主导:活跃被利用(KEV)的发现排在最前,然后是 严格的严重性等级,只有在 *同一等级内*,爆炸半径才会打破平局。 这确保了一个仓库中的严重 CVE 排名高于一个影响数千个仓库但级别较低的不可靠 代码检查 —— 这与 `impact` 的权衡恰恰相反,后者会将 范围广但仅作为信息提示的警告置于顶部。 `remediation` 视图更进一步。`fix-first` 对 *是哪个安全公告* 进行排序,而此视图 输出 *该采取什么措施*:具体的依赖升级。每一 行都是 **批量处理** 的,因此一个单独的 `bump tokio 1.0 → 1.38` 行即可解决 每一次升级在所有仓库中能够解决的所有安全公告,并且破坏性(semver-major)的跨版本升级会被 标记出来,以便优先处理影响小的修复。没有发布修复补丁的安全公告会被 如实标注(`no fix: …`),而不是粉饰为升级。当静态 可达性分析运行后(`--reachability=static`),*被证明* 不可达的安全公告会降至 信息性尾部(会显示,但绝不会排入修复队列中),因此 死代码发现永远不会挤占真正重要的升级操作。 ### 追踪随时间的漂移 `fleetreach diff ` 比较两份保存的报告(每份 均来自 `scan -f json`),并将发现结果分为 **新增**、**已修复** 和 **仍然存在** —— 这是单次扫描无法回答的问题:*这个分支使群体变得更好还是更糟?* 新增的安全公告是倒退;已修复的是进步;一个 仍然存在但仓库影响范围缩小或扩大的公告会显示 `±` 爆炸半径 漂移。它是纯粹的(无需扫描、数据库或网络 —— 仅需两个 JSON 文件),因此可以直接 作为轻量级检测关卡加入到 CI 中: ``` 1 new, 1 fixed, 1 still open. New (1): critical RUSTSEC-2026-9999 2 (+2) brand new critical ``` 退出代码与 `scan` 一致:`0` 安全,`1` 表示 *新增* 的发现触发了关卡,`2` 表示 无法读取文件。`--fail-on ` 设置了新增漏洞必须 达到才能触发关卡的最低门槛(默认为 `low`;Unknown 总是计入,失败即关闭),`--fail-on-warnings` 也会在新引入的警告处触发关卡,而 `--exit-zero` 使其仅作报告而不拦截。 `-f json` 输出完整的结构化差异以供自动化使用。 ### GitHub Action 使用内置的组合 Action 将发现结果放入 Security(安全)标签页并添加 PR 注释 (参见 [`.github/workflows/audit-example.yml`](.github/workflows/audit-example.yml)): ``` - uses: tess-fun/fleetreach@v1 with: args: "--enrich --resolve-features" ``` `fleet.toml` 列出了要扫描的仓库: ``` [[repo]] id = "core-lib" path = "../core-lib" # repo root; Cargo.lock located within [[repo]] id = "services" path = "../services" glob = true # discover **/Cargo.lock under the tree glob_max_depth = 4 # bounded; default 3 [[repo]] id = "billing-api" path = "../billing-api" # a go.mod repo; scanned via govulncheck ecosystem = "go" # optional; auto-detected from the manifests [[repo]] id = "web-frontend" path = "../web-frontend" # a package-lock.json repo; toolchain-free OSV match ecosystem = "npm" # optional; auto-detected from the manifests [[repo]] id = "ml-service" path = "../ml-service" # a uv.lock/poetry.lock/Pipfile.lock repo; toolchain-free ecosystem = "pypi" # optional; auto-detected from the manifests [[repo]] id = "storefront" path = "../storefront" # a composer.lock repo; toolchain-free OSV match ecosystem = "packagist" # optional; auto-detected from the manifests [[repo]] id = "payments-dotnet" path = "../payments-dotnet" # a packages.lock.json repo; toolchain-free OSV match ecosystem = "nuget" # optional; auto-detected from the manifests [[repo]] id = "sim-pipeline" path = "../sim-pipeline" # a Manifest.toml repo; toolchain-free OSV match ecosystem = "julia" # optional; auto-detected from the manifests [[repo]] id = "ios-client" path = "../ios-client" # a Package.resolved repo; toolchain-free OSV match ecosystem = "swift" # optional; auto-detected from the manifests [[repo]] id = "billing-api" path = "../billing-api" # a Gemfile.lock repo; toolchain-free OSV match ecosystem = "rubygems" # optional; auto-detected from the manifests [[repo]] id = "chat-service" path = "../chat-service" # a mix.lock repo; toolchain-free OSV match ecosystem = "hex" # optional; auto-detected from the manifests [[repo]] id = "analytics-jvm" path = "../analytics-jvm" # a gradle.lockfile/pom.xml repo; toolchain-free OSV match ecosystem = "maven" # optional; auto-detected from the manifests [[repo]] id = "ci-config" path = "../ci-config" # a .github/workflows repo; scans pinned `uses:` actions ecosystem = "githubactions" # set explicitly to scan a package repo's workflows too [[settings.ignore]] id = "RUSTSEC-2020-0071" reason = "dev-dependency only, not in any shipped path" # REQUIRED, non-empty ``` 包含 `go.mod`(且没有 `Cargo.lock`)的仓库会被 `govulncheck` 扫描,并 汇入同一份群体报告中,因此一个混合了 Rust 和 Go 的群体会产生一个统一的、具备爆炸半径 和可达性感知的修复队列。由于 govulncheck 需要编译 module,Go 扫描需要 `--allow-untrusted-builds` 以及一个 `govulncheck` 二进制文件(通过 `--govulncheck` 指定, 或者在 `PATH`/`$GOPATH/bin` 中);如果没有这些,Go 仓库会被报告为错误缺口, 而不是被静默跳过。确认的 Go 调用点会被标记为 `reachable`(该 分析是可靠阳性的),而存在但未被调用的保持为 `unknown`,绝不会出现错误的“不可达”。 没有 Go 工具链?一种降级的 **module 级别** 模式会读取 `go.mod` 并 将每个依赖与 vuln.go.dev 镜像进行匹配(`--go-vuln-db=file://`)—— 它不编译 任何东西,因此不需要 `--allow-untrusted-builds`。它仅限于 module 级别(发现结果的 可达性为 `unknown`,没有符号分析),并且无法看到 Go stdlib 公告,但 其匹配机制已经过与 govulncheck 在真实 module 上的差异性验证,保证 **零误报安全**。 其他每个生态系统都以同样 **无需工具链** 的方式进行扫描:`fleetreach` 读取 lockfile(完整的传递依赖树,已固定到确切版本),并将每个 包与通过 `---vuln-db=file://` 传入的 **OSV 镜像** 进行匹配,指向 osv.dev 导出的 `all.zip`(每个生态系统位于 `https://osv-vulnerabilities.storage.googleapis.com//all.zip`,可直接读取 无需解压)或一个包含解压记录的目录。它不运行任何包管理器,也没有 安装或构建脚本,因此与 Go 的 module 级别模式一样,它在构建上是安全的,并且 不需要 `--allow-untrusted-builds`;如果没有镜像,该仓库就是一个如实的错误缺口, 绝不静默跳过。严重性来自 GHSA 等级或 CVSS 向量,直接与 间接的区分来自 lockfile,除非运行了可达性 模式,否则发现结果的可达性均为 `unknown`。 | 生态系统 | Lockfile | 标志 | 版本语义 | |-----------|-------------|------|-------------------| | npm | `package-lock.json` | `--npm-vuln-db` | SemVer | | PyPI | `uv.lock` / `poetry.lock` / `Pipfile.lock` | `--pypi-vuln-db` | PEP 440 (PEP 503 名称) | | RubyGems | `Gemfile.lock` | `--rubygems-vuln-db` | `Gem::Version` | | Packagist | `composer.lock` | `--packagist-vuln-db` | Composer `version_compare` | | NuGet | `packages.lock.json` | `--nuget-vuln-db` | 四段式 `NuGetVersion` | | Julia | `Manifest.toml` | `--julia-vuln-db` | `VersionNumber` | | Swift | `Package.resolved` | `--swift-vuln-db` | URL 标识的 SemVer | | Hex | `mix.lock` | `--hex-vuln-db` | SemVer | | Maven | `gradle.lockfile` / `pom.xml` | `--maven-vuln-db` | `ComparableVersion` | | GitHub Actions | `.github/workflows/*.yml` | `--ghactions-vuln-db` | tag SemVer | 有一些细节无法填入表格。当公告列举的是受影响的版本而非 范围时(特别是恶意软件 `MAL-` 记),匹配器会同时查阅这两个列表。PyPI 根据 PEP 503 规范化名称,因此 `Flask` 和 `flask` 能匹配上。对于 GitHub Actions,仅 匹配固定了版本的 `uses:` 引用(例如 `tj-actions/changed-files` 供应链公告),而 SHA 和分支固定会被作为如实的缺口跳过。每个定制 比较器都与现有的真实上游库进行了差异性验证:Maven 比较器与 Apache Maven 自带的 `ComparableVersion` 在超过 710,000 个版本 对上保持一致,而 npm/PyPI/RubyGems 的匹配在针对 OSV 导出数据验证时 达到了 100% 的召回率和零误报安全。 一个混合生态系统的群体 —— Rust、Go 以及任何无需工具链的输入源 —— 都能汇入一个 统一的、按爆炸半径排序的修复队列。 核心标志:`--db ` (使用本地 advisory-db 克隆), `--offline`, `--max-db-age 7d`, `--min-severity high`, `--fail-on critical`, `--fail-on-warnings`。详见 `fleetreach scan --help`。 ### 根据真实世界风险确定优先级 `--enrich` 使用 **CISA KEV**(在野被积极利用)和 **FIRST EPSS**(漏洞利用概率)对每个发现进行注释,将它们重新排序为一个行动 队列,并添加一个 `Risk` 列: ``` Severity Risk Advisory Fix Title critical 9.8 epss 88% RUSTSEC-2021-0097 openssl-src → 111.16.0 SM2 decryption buffer overflow high 7.5 epss 71% RUSTSEC-2022-0014 openssl-src → 111.18.0 infinite loop in BN_mod_sqrt high 7.4 epss 50% RUSTSEC-2021-0098 openssl-src → 111.16.0 ASN.1 read buffer overruns high 7.5 epss 14% RUSTSEC-2022-0013 regex 1.5.4 → 1.5.5 regex repetition DoS critical 9.8 epss 2% RUSTSEC-2021-0003 smallvec 1.6.0 → 0.6.14 SmallVec::insert_many overflow ``` 两个 `critical 9.8` 的 CVSS 评分相同,但 EPSS 打破了平局:openssl 溢出(88% 的利用概率)升至队列首位,而 smallvec(2%)则降至接近底部。在 CISA 已知被利用列表中的发现会在 `Risk` 列中显示为 `KEV epss NN%`。 使用 `--fail-on-kev`(如果有任何漏洞被积极利用则失败)或 `--min-epss 0.5` 设置关卡。这两个数据源都可以通过 `--kev-file` / `--epss-file` 离线提供。 每个发现都显示了其 **依赖来源**:被标记的包是 直接依赖还是间接依赖,以及引入它的依赖链: ``` fleetreach/proc-macro-error2@2.0.1 (via fleetreach-scan → … → defmt-macros) ``` 完整的链条保存在 JSON (`occurrences[].dependency_path`) 中,因此无需 使用 `cargo tree -i` 即可查看 *是谁引入了某个包*。`--why ` 可以一次性针对整个群体提出这个问题: ``` $ fleetreach scan --why serde cli-tools — serde 1.0.228 (direct): ripgrep → serde docs-builder — serde 1.0.228 (transitive): guide-helper → serde_json → serde file-finder — serde 1.0.228 (transitive): fd-find → globset → bstr → serde ``` 借助 **`--resolve-features`**(可选开启,需要仓库可构建的源码),每个 发现也会被标记为已构建,还是仅存在于 `Cargo.lock` 中且从未被编译的 虚幻可选依赖;表格会用 `⚠ not in default build` 标记这些情况,并且 JSON 中会增加 `occurrences[].active` 字段。默认扫描依然保持仅读取 lockfile 且 具备良好的可移植性。 本仓库自身也进行了自我测试:提交的 [`fleet.toml`](fleet.toml) 指向 仓库根目录,因此从这里运行 `fleetreach scan` 会审计 fleetreach 自身的依赖 树(它报告了零漏洞)。 ## 退出代码 (CI 契约) 自上而下评估,匹配到第一个即生效: | 代码 | 含义 | |------|---------| | `3` | 用法 / 参数错误。 | | `2` | 无法完成可信的扫描:配置无效 · advisory DB 无法加载 · DB 早于 `--max-db-age` · 零个仓库被扫描 · **任何仓库报错**(缺口意味着我们无法宣称整个群体是安全的)。 | | `1` | 可信的扫描;有发现结果触发了拦截(`--fail-on` 或 `--fail-on-warnings`)。 | | `0` | 可信的扫描;没有任何内容达到失败阈值。 | 错误的“安全报告”是最糟糕的输出结果,因此除非完成了一次它能够 完全认可的扫描,否则该工具绝不会以 `0` 退出。 ## 设计决策 (失败即关闭) `fleetreach` 宁愿产生噪音也不愿保持沉默:当它无法 *证明* 某些事物是 安全的时,它会将其暴露出来,而不是悄然放过。 - **未知严重性的漏洞总会触发关卡。** 没有 CVSS 评分的安全公告会被报告为 `unknown` 严重性。它仍会触发 `--fail-on` 并且仍会 在 `--min-severity` 过滤中保留;我们无法证明它低于 阈值,所以我们绝不会静默丢弃它。 - **`--db-rev` 需要 `--db`。** 将 advisory DB 固定到确切的 commit 仅对本地的 advisory-db git 克隆有效(`rustsec` 0.33 没有暴露 按版本打开的构造器;该固定操作是通过检出克隆来实现的)。 - **`--max-db-age` 在库时间未知时拒绝运行。** 如果 DB 不包含 commit 时间戳,则无法验证其新鲜度,因此运行将以 `2` 退出,而 不是假定 DB 是最新的。 ## 架构 ``` cli → report → correlate → scan → core ``` 依赖关系严格向内指向。`core`(领域模型和 JSON 通信 契约)在工作区内没有任何依赖,其公开 API 中也没有 `rustsec` 类型,因此未来的数据丰富化将作为附加字段添加,而不会破坏 `schema_version: 1`。`scan` 是唯一触碰 `rustsec` 的 crate。每个 crate 都禁止 `unsafe`,并拒绝在 外部派生的值上使用 `unwrap`/`expect`/`panic` 系列。 有关完整的数据流和失败即关闭 主轴,请参见 [ARCHITECTURE.md](ARCHITECTURE.md),发布说明请参见 [CHANGELOG.md](CHANGELOG.md)。 ## 可达性 `--reachability`(单独使用,或者 `=heuristic`)是一种带标签的源码存在 *启发式方法*,它会 grep 你的源码但从不构建任何东西。对于 Rust,它会 grep 公告中受影响的函数名;对于无需工具链的输入源,它会 grep 每个 **直接** 依赖的 import/use 语句 —— 对于 npm/Julia/RubyGems 是精确匹配 (坐标 = import 名),而对于 PyPI/NuGet/Maven/Packagist/Swift/Hex 则是通过各生态系统的名称启发式方法进行匹配 (dist→module, package-id→namespace, group→Java-package, vendor/pkg→PSR-4, repo→Swift-module, `foo_bar`→`FooBar`)。对于 GitHub Actions,一个 `uses:` 引用就是一个活跃的 CI 步骤(可靠阳性)。该 启发式方法只会在阳性匹配时将发现 *提升* 为可达 —— 它永远不会 将 Tier-C 的发现标记为不可达,因此漏掉的 import 无法隐藏漏洞 (并且 `--reachable-only` 绝不会因为 grep 未命中而放弃某个漏洞)。目前所有 12 个生态系统都会 产生可达性信号(Go 通过 govulncheck;Cargo 还具有下文提到的可靠静态 模式)。 **npm 导入图。** 在 `--reachability` 下,npm 使用无构建的 *module 导入 图* 来代替扁平的 grep:它会解析你源码中的每个 `require`/`import`,以及(当存在 `node_modules` 时)每个已安装包中的导入,然后报告 有漏洞的包为 `Reachable`,并提供见证导入链(`your-dep → … → vuln`)—— 包括传递依赖包。`--npm-prune-unreachable` 额外地 在存在 `node_modules` 且没有导入路径到达该包时将其标记为 `NotReachable`(因此 `--reachable-only` 会将其丢弃)。这种否定性结果是尽力而为的可靠判定:一个 它无法看到的动态 `require(expr)` 或框架自动加载可能会使得 `NotReachable` 变得不准确,这就是为什么它是一个单独的显式可选开启项。 `--reachability=static` 是一种可靠的 MIR 调用图分析,它可以证明存在漏洞的 函数是否可被调用,并提供见证链。 ## MSRV 最低支持的 Rust 版本为 **1.89**(由依赖闭包决定, 而不仅仅是 `rustsec`),已在 CI 中验证。 ## 许可证 根据以下任一许可证授权: - Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) 或 http://www.apache.org/licenses/LICENSE-2.0) - MIT license ([LICENSE-MIT](LICENSE-MIT) 或 http://opensource.org/licenses/MIT) 由你选择。 ### 贡献 除非你明确声明,否则任何由你有意提交以包含在 作品中的贡献,根据 Apache-2.0 许可证的定,均应按上文所述进行 双重许可,无需任何附加条款或条件。
标签:GPT, Rust, 代码可达性分析, 依赖审计, 可视化界面, 漏洞管理, 网络流量审计, 通知系统