# scala-dep-scan
一款快速的、零依赖的 Rust CLI 工具,用于扫描 Scala/Play/SBT 项目中存在漏洞、过时和未使用的依赖项。专为维护旧代码库的团队构建。
**单一二进制文件。无需 JVM。几秒钟即可完成扫描,无需几分钟。**
```
$ scala-dep-scan /path/to/project --osv
Dependencies: 54 direct + 12 transitive
Risk flags: 7 Critical 2 High 3 Medium 4 Low
CRITICAL com.typesafe.play:play-json:2.3.2 [KNOWN-CVE]
-> Multiple RCE and CSRF vulnerabilities in Play < 2.8
CVEs: CVE-2019-17598, CVE-2018-6003
Fix: Upgrade to >= 2.8.0
10 file(s) reference this dependency
CRITICAL mysql:mysql-connector-java:5.1.31 [OSV-ADVISORY]
-> Improper Access Control in MySQL Connectors Java
CVEs: GHSA-2xxh-f8r3-hvvr
```
## 为什么选择 scala-dep-scan?
| 功能 | scala-dep-scan | sbt-dependency-check | Snyk | Dependabot |
| ----------------------- | :------------: | :------------------: | :-----: | :--------: |
| 无需 JVM | 是 | 否 | 否 | 否 |
| 扫描速度 | <5s | 分钟 | 分钟 | 异步 |
| 未使用依赖检测 | 是 | 否 | 否 | 否 |
| 代码引用扫描 | 是 | 否 | 否 | 否 |
| 自动修复未使用依赖 | 是 | 否 | 否 | 否 |
| SBOM 生成 | 是 | 是 | 是 | 否 |
| 离线模式 | 是 | 否 | 否 | 否 |
| 许可证合规 | 是 | 否 | 是 | 否 |
| 交互式 TUI | 是 | 否 | 否 | 否 |
| 多模块 SBT | 是 | 是 | 是 | 是 |
| CI 退出码 | 是 | 是 | 是 | 否 |
| 单一二进制文件 | 是 | 否 | 否 | 否 |
| 免费且开源 | 是 | 是 | 否 | 是 |
## 快速开始
### 安装
```
# macOS (Homebrew)
brew install humancto/tap/scala-dep-scan
# 从源码构建 (任何具备 Rust 的平台)
cargo install --path .
# 预编译二进制文件 (Linux x86_64)
chmod +x scala-dep-scan-linux-x86_64
./scala-dep-scan-linux-x86_64 /path/to/project
# 从源码构建 macOS (一次性设置)
./install-mac.sh
```
### 基本用法
```
# 扫描当前目录
scala-dep-scan .
# 结合 OSV advisory 查询的完整扫描
scala-dep-scan /path/to/project --osv
# 仅显示 HIGH+ 严重性
scala-dep-scan . -s high
# 用于 CI 的 JSON 输出
scala-dep-scan . -f json | jq '.summary'
# 交互式 TUI 浏览器
scala-dep-scan . --tui
# 用于 CI 的静默模式 (仅 exit code)
scala-dep-scan . -q -s critical
```
## 功能特性
### 风险检测
三层漏洞检测:
1. **嵌入式数据库** - 80+ 个已知的高危依赖项(Log4Shell、Spring4Shell、Jackson 反序列化、commons-collections RCE、H2 RCE、Text4Shell、XStream、Jetty 等)
2. **陈旧性启发式分析** - 预发布版本、带日期版本的构件、已弃用的包
3. **OSV.dev API** - 针对开源漏洞数据库的实时建议查询(`--osv` 标志)
```
# 结合 network advisory 查询的完整扫描
scala-dep-scan . --osv
# 启用响应缓存 (默认 TTL 为 24h)
scala-dep-scan . --osv # first run: queries API
scala-dep-scan . --osv # second run: uses cache
scala-dep-scan . --osv --no-cache # bypass cache
```
### 未使用依赖检测
深度符号级分析可识别以下依赖:
- **未使用** - 代码中没有任何 import 或符号引用
- **死导入** - 已导入但从未实际调用
- **活动** - 已确认在代码中使用的符号
- **仅运行时** - 在运行时注入(Guice、logback、测试框架)
```
# 显示使用情况分析
scala-dep-scan . --unused
# 自动从 build.sbt 移除未使用的 deps
scala-dep-scan . --fix-unused --dry-run # preview changes
scala-dep-scan . --fix-unused # apply changes (creates .bak backup)
```
### 依赖关系图
以多种格式可视化您的依赖树:
```
# 终端彩色 ASCII 树 (默认)
scala-dep-scan .
# Graphviz DOT 文件
scala-dep-scan . --dot deps.dot
dot -Tsvg deps.dot -o deps.svg # render to SVG
# JSON 邻接表
scala-dep-scan . --graph-json deps.json
```
### 代码引用扫描
查找每一个导入了标记依赖项的 `.scala` 和 `.java` 文件,准确显示风险代码的位置:
```
CRITICAL com.typesafe.play:play-json:2.3.2 [KNOWN-CVE]
10 file(s) reference this dependency:
.../StickerImageActor.scala:16 -> play.api.libs.json.Json
.../RedisBrowseNodeProducer.scala:9 -> play.api.libs.json.Json
.../OfferPublisherActor.scala:20 -> play.api.libs.json.Json
... and 7 more
```
### 配置与忽略文件
确认已知风险并设置项目级策略:
```
# 生成预填充所有当前发现的配置
scala-dep-scan . --init
# 编辑 .scala-dep-scan.yaml 以确认已接受的风险
```
```
# .scala-dep-scan.yaml
version: 1
severity_threshold: low
ignore:
- coord: "com.typesafe.play:play"
reason: "Migration to Play 2.8 scheduled for Q2"
expires: "2026-06-01"
- cve: "CVE-2015-6420"
reason: "Not exploitable in our deployment"
expires: "2026-12-31"
```
### SBOM 生成
生成行业标准格式的软件物料清单 (SBOM):
```
# CycloneDX 1.5 JSON
scala-dep-scan . --sbom cyclonedx --sbom-output sbom-cdx.json
# SPDX 2.3 JSON
scala-dep-scan . --sbom spdx --sbom-output sbom-spdx.json
```
### 许可证合规
扫描并强制执行许可证策略:
```
# 显示所有依赖的许可证信息
scala-dep-scan . --license
# 强制执行许可证策略
scala-dep-scan . --license --license-policy "allow:MIT,Apache-2.0 deny:GPL-3.0"
```
### 升级顾问
获取包含工作量估算的可操作迁移指导:
```
scala-dep-scan . --upgrade-plan
```
```
Upgrade Plan (prioritized by risk and effort):
1. com.typesafe.play:play 2.3.2 -> 2.8.19
Risk: CRITICAL | Effort: ~40 hours | 193 code references
Breaking changes:
- play.api.mvc.Controller removed, use BaseController
- play.api.libs.json.Json.parse throws on invalid JSON
- Configuration API changed to typesafe config
Migration guide: https://www.playframework.com/documentation/2.8.x/Migration28
2. mysql:mysql-connector-java 5.1.31 -> 8.0.33
Risk: CRITICAL | Effort: ~4 hours | 27 code references
Breaking changes:
- Package renamed to com.mysql.cj.jdbc
- SSL enabled by default
```
### 陈旧度评分
通过版本年代分析量化技术债:
```
scala-dep-scan . --staleness
```
### 策略即代码
定义并强制执行组织级的依赖策略:
```
# .scala-dep-scan.yaml
policies:
- name: "no-ancient-deps"
rule: "version_age_months < 36"
severity: high
message: "Dependencies must be updated within 3 years"
- name: "no-pre-release"
rule: "version !~ /^0\\./"
severity: medium
```
```
scala-dep-scan . --policy org-policy.yaml
```
### HTML 仪表板
生成可共享的报告:
```
scala-dep-scan . --html report.html
```
自包含的单一 HTML 文件,包含执行摘要、交互式依赖树、可搜索的风险表和用法分析图表。
### 扫描对比 / Diff
跨提交跟踪修复进度:
```
# 保存 baseline
scala-dep-scan . --save-baseline baseline.json
# 与 baseline 进行比较 (例如在 PR 中)
scala-dep-scan . --compare baseline.json
# 显示: 2 个 NEW 发现, 3 个 RESOLVED, 11 个 UNCHANGED
# Exit code: 仅针对 NEW critical/high 失败
```
### 交互式 TUI 浏览器
交互式浏览依赖项:
```
scala-dep-scan . --tui
```
三面板终端 UI,包含:
- 带有严重性图标的可滚动依赖列表
- 包含风险信息、CVE、使用情况、代码引用的详情视图
- 搜索、按严重性过滤、按名称/风险/使用情况排序
- 键盘驱动:`j/k` 导航,`/` 搜索,`f` 过滤,`q` 退出
### CI 集成
```
# GitHub Actions
- name: Scan dependencies
run: |
scala-dep-scan . --osv -s high -q
# exits 1 on HIGH, 2 on CRITICAL
# 自动生成 CI 配置
scala-dep-scan --generate-ci github > .github/workflows/dep-scan.yml
scala-dep-scan --generate-ci gitlab > .gitlab-ci.yml
```
退出码:
- `0` - 干净(未发现 HIGH/CRITICAL 级别的问题)
- `1` - 检测到 HIGH 严重级别的问题
- `2` - 检测到 CRITICAL 严重级别的问题
### 多模块 SBT 项目
自动检测多模块构建:
```
scala-dep-scan /path/to/monorepo
# 扫描所有子项目,按 module 分组发现
```
支持:
- 包含 `lazy val` 子项目的 `build.sbt`
- `project/Build.scala`
- `.dependsOn()` 和 `.aggregate()` 关系
## 输出格式
### 终端(默认)
彩色编码的 ASCII 树 + 风险发现,包含 CVE ID、修复建议和代码引用。
### JSON (`-f json`)
```
{
"summary": {
"direct_deps": 54,
"transitive_deps": 0,
"total_flags": 10,
"critical": 4,
"high": 1,
"medium": 1,
"low": 4,
"unused_deps": 12,
"dead_import_deps": 3,
"private_deps": 8,
"private_deps_note": "Private/internal dependencies cannot be scanned against public vulnerability databases"
},
"risk_flags": [...],
"dependency_usage": [
{"coord": "com.example:lib", "verdict": "Unused", "usage_count": 0},
{"coord": "com.example:used-lib", "verdict": "Active", "usage_count": 15, "symbols_found": ["Json", "Reads"]}
],
"code_references": { "org:name": [...] },
"graph": { "nodes": [...], "edges": [...] }
}
```
### DOT 图 (`--dot`)
带有颜色编码风险节点的 Graphviz 格式。使用 `dot -Tsvg` 渲染。
### HTML (`--html`)
自包含的仪表板报告。
### SBOM (`--sbom`)
CycloneDX 1.5 或 SPDX 2.3 JSON。
## 架构
```
src/
├── main.rs # CLI entry, orchestration
├── types.rs # Shared data structures
├── config.rs # Config/ignore file (.scala-dep-scan.yaml)
├── parser/mod.rs # build.sbt + lockfile parsers (regex-based)
├── risk.rs # Risk engine: known-bad DB + heuristics + OSV
├── graph.rs # petgraph dep graph + DOT/ASCII/JSON renderers
├── scanner.rs # Scala/Java import reference scanner
├── report.rs # Terminal + JSON report formatters
├── rewriter.rs # build.sbt rewriter (--fix-unused)
├── sbom.rs # SBOM generation (CycloneDX, SPDX)
├── license.rs # License compliance checking
├── staleness.rs # Dependency age/staleness scoring
├── advisor.rs # Upgrade path advisor with migration guides
├── policy.rs # Policy-as-code engine
├── html_report.rs # HTML dashboard generator
├── diff.rs # Scan diff/comparison mode
├── ci_templates.rs # CI config generators
└── tui.rs # Interactive TUI explorer (ratatui)
data/
└── risky_deps.json # Embedded risk database (compiled into binary)
tests/
└── *.rs # Comprehensive test suite
```
## 风险数据库
涵盖 80 多个最关键的 JVM 漏洞条目。定期更新。
| 类别 | 库 | 关键 CVE |
| ------------------- | --------------------------------------------------------------- | ------------------------------ |
| **框架** | Play Framework, Spring, Akka HTTP | CVE-2019-17598, CVE-2022-22965 |
| **日志** | Log4j (Log4Shell), Logback | CVE-2021-44228, CVE-2023-6378 |
| **序列化** | Jackson, XStream, SnakeYAML, Kryo | CVE-2020-36518, CVE-2021-21351 |
| **Apache Commons** | collections, text (Text4Shell), compress, fileupload, beanutils | CVE-2015-7501, CVE-2022-42889 |
| **HTTP/网络** | Netty, Jetty, OkHttp, HttpClient, Undertow | CVE-2021-43797, CVE-2023-26048 |
| **数据库** | MySQL, PostgreSQL, H2 (RCE), SQLite | CVE-2021-42392, CVE-2022-21724 |
| **加密** | BouncyCastle, Apache Shiro, Nimbus JOSE | CVE-2020-26939, CVE-2023-46749 |
| **XML/模板** | dom4j, Woodstox, Velocity, FreeMarker | CVE-2020-10683, CVE-2020-7009 |
此外,通过 **OSV.dev API** 进行实时查询以获取实时建议数据。
## 许可证
根据 Apache License 2.0 版授权。详情请参阅 [LICENSE](../LICENSE)。
## 致谢
- [OSV.dev](https://osv.dev/) 提供漏洞建议数据
- [petgraph](https://github.com/petgraph/petgraph) 提供依赖图算法
- [ratatui](https://github.com/ratatui-org/ratatui) 提供终端 UI 框架
- [clap](https://github.com/clap-rs/clap) 提供 CLI 参数解析