IcebergAI/IcebergSCA
GitHub: IcebergAI/IcebergSCA
IcebergSCA 是一款面向软件项目的供应链安全分析 CLI 工具,基于 lockfile 优先策略扫描依赖并匹配 OSV 漏洞数据库,诚实地报告每个依赖的已知漏洞与检查状态。
Stars: 0 | Forks: 0
# IcebergSCA
用于软件项目的供应链分析。将其指向一个目录;它会找到每一个依赖清单和 lockfile,构建直接和间接依赖集,在 [OSV](https://osv.dev) 中查找每个包,并报告其发现的内容。
文档:

## 安装
它是一个 CLI 应用程序,而不是一个库依赖——请将其作为工具安装:
```
uv tool install icebergsca # or: uvx icebergsca scan .
pipx install icebergsca
```
## 用法
```
icebergsca scan ./myproject
icebergsca scan ./myproject --format json --output report.json
icebergsca scan ./myproject --include-dev
icebergsca scan ./myproject --ecosystem pypi,npm --exclude 'fixtures/**'
icebergsca scan ./requirements.txt # a single file works too
icebergsca sbom ./myproject # CycloneDX 1.6, components only
icebergsca sbom ./myproject --with-vulnerabilities # ...plus a VEX section
icebergsca cache info | clear | prune
```
报告输出会发送到 stdout,日志会发送到 stderr,因此 `--format json | jq` 的结果总是很干净。
Monorepo 会生成一个合并的报告,按清单分组,每一条发现都会带有引入它的文件:

## 设计
**优先使用 Lockfile。** 在存在 lockfile 的情况下,解析后的依赖图将直接从中读取——因此报告描述的是实际安装的内容,而不是如果今天去解析会得到什么。只有在没有 lockfile 的情况下,它才会回退到根据 registry 解析版本范围,并且这些发现会被标记为 `resolved` 而不是 `pinned`。Java 没有 lockfile,其依赖图会从 Maven Central 重建,并标记为 `~` 表示近似值。
**绝不在不干净的时候声称干净。** 这是所有其他设计都要围绕的核心约束:
- 由于查找未运行而导致的空发现列表会被报告为*“漏洞查找未运行”*,绝不会是*“未发现漏洞”*。JSON 会携带一个明确的 `vulnerabilities_checked` 标志,而 SBOM 会携带一个 `icebergsca:vulnerabilitiesChecked` 属性。
- 无法向 OSV 查询的包会被单独列为未检查项。
- 如果无法访问 OSV,则会使用过期的缓存条目,并将其标记为过期,而不是静默地什么都不返回。
- 如果 lockfile 解析失败,会回退到其清单,*并带有警告*提示版本是声明安装的而非实际已安装的。
- 被跳过的文件、被截断的依赖图和未解析的约束都会被计数并显示。
**查找结果绝不会导致您的构建失败。**
| 退出代码 | 含义 |
|---|---|
| `0` | 扫描完成。可能发现了漏洞——这并不是错误 |
| `1` | 扫描失败,或仅部分完成——某些文件或包未被检查 |
| `2` | 使用错误:错误的 flag、未知的格式(Click 保留的代码) |
基于严重程度的 CI 门控(`--fail-on`)已在计划中;报告模型已经包含了实现它所需的一切。
## 生态系统支持
| 生态系统 | 清单 | Lockfiles | 依赖图边 |
|---|---|---|---|
| Python | `requirements*.txt`, `pyproject.toml`, `setup.cfg`, `Pipfile` | `uv.lock`, `poetry.lock`, `Pipfile.lock` | 是 |
| npm | `package.json` | `package-lock.json` (v1–v3), `pnpm-lock.yaml`, `yarn.lock` (v1 + Berry) | 是 |
| Maven / Gradle | `pom.xml`, `build.gradle(.kts)` | *无* — 从 Central 解析 | 是(近似) |
| Go | — | `go.mod` (已经过 MVS 解析) | 否 |
| Rust | `Cargo.toml` | `Cargo.lock` | 是 |
| .NET | `*.csproj`, `packages.config` | `packages.lock.json` | 是 |
| Ruby | `Gemfile`, `*.gemspec` | `Gemfile.lock` | 是 |
故意不使用 `go.sum`:它列出了在解析过程中*考虑*过的所有版本,而不是被选中的版本,因此扫描它会报告从未构建过的代码中的漏洞。
## 输出格式
| `--format` | 用途 |
|---|---|
| `table` | 人类可读的终端输出(默认) |
| `json` | 全保真文档——包含每一个依赖、发现、来源和警告 |
| `csv` | 每个引入清单的每个发现一行,适用于电子表格 |
| `sarif` | 用于 GitHub 代码扫描的 SARIF 2.1.0,带有稳定的指纹 |
| `cyclonedx` | CycloneDX 1.6 — 一个集 SBOM 和 VEX 文档于一体的文件 |
SARIF 和 CycloneDX 会在测试套件中与官方发布的 schema 进行验证。
### GitHub Actions
```
- run: uvx icebergsca scan . --format sarif --output icebergsca.sarif
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: icebergsca.sarif
```
## 对于 AI 代理
IcebergSCA 在包中内置了一个代理技能,遵循与 FastAPI、Typer 和 SQLModel 相同的惯例:
```
icebergsca/.agents/skills/icebergsca/SKILL.md
/references/json-report.md
/references/ci-integration.md
```
在安装后,使用 glob 匹配 site-packages 以查找 `SKILL.md` 的代理将自动找到它。它涵盖了调用方式、JSON schema、退出代码语义,以及最重要的——在将项目报告为干净之前必须检查的三个字段。一个空的 `findings` 数组意味着“已检查且干净”、“从未检查”或“部分检查”,只有报告本身才能说明是哪一种。
## 缓存
结果缓存在用户级缓存目录下的 SQLite 中。建议详情以 OSV 返回的 `modified` 时间戳为键,因此修订后的建议会落入一个新的键下——这是精确的失效,而不是靠猜测的 TTL。`--offline` 仅提供缓存服务,并将任何未缓存的内容报告为未检查;`--refresh` 会首先丢弃缓存。
## 开发
```
uv sync --extra dev
uv run ruff check . && uv run ruff format --check .
uv run mypy
uv run pytest
```
测试套件从不接触网络:一个 autouse fixture 会将 HTTP 客户端替换为 mock transport,对任何未显式 stub 的请求返回 404,因此如果测试尝试进行外部网络请求就会失败,而不是因为错误的原因而通过。
## 许可证
Apache License 2.0 — 参见 [LICENSE](LICENSE) 和 [NOTICE](NOTICE)。
标签:CycloneDX, SBOM, 硬件无关, 软件供应链安全, 远程方法调用, 逆向工具