codelake-dev/licscan
GitHub: codelake-dev/licscan
一款开源的代码库许可证与合规扫描器,支持生成 SBOM 并提供 EU CRA 合规证据。
Stars: 1 | Forks: 0
```
_ _ _____
| | (_) / ____|
| | _ ___| (___ ___ __ _ _ __
| | | |/ __|\___ \ / __/ _` | '_ \
| |____| | (__ ____) | (_| (_| | | | |
|______|_|\___|_____/ \___\__,_|_| |_|
```
**面向现代代码库的开源许可证与合规扫描器。**
[](https://github.com/codelake-dev/licscan/actions/workflows/ci.yml)
[](https://github.com/codelake-dev/licscan/releases)
[](LICENSE)
[](https://pkg.go.dev/github.com/codelake-dev/licscan)
[](https://goreportcard.com/report/github.com/codelake-dev/licscan)
[](https://github.com/marketplace/actions/licscan)
## 什么是 licscan?
`licscan` 会扫描项目的依赖项许可证,按风险对它们进行分类,检查这些依赖组合是否可以发布,并导出符合标准的 SBOM(CycloneDX 1.5 / SPDX 2.3)。
它专为希望将许可证合规性作为 CI 中确定性的、可脚本化的一部分的工程团队而构建——而不是每季度应对一次的紧急演习。
### 支持的包管理器
| 生态系统 | 清单文件 |
|---|---|
| PHP | `composer.json`, `composer.lock` |
| Node.js | `package.json`, `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml` |
| Python | `requirements.txt`, `Pipfile.lock`, `poetry.lock`, `pyproject.toml` |
| Go | `go.mod`, `go.sum` |
| Ruby | `Gemfile`, `Gemfile.lock` |
| Rust | `Cargo.toml`, `Cargo.lock` |
| Java | `pom.xml`, `build.gradle`, `build.gradle.kts` |
### 风险分类
| 标记 | 分类 | 示例 |
|---|---|---|
| ✅ | 宽松型 | MIT, Apache-2.0, BSD-2-Clause, BSD-3-Clause, ISC |
| ⚠️ | 弱 Copyleft | LGPL-2.1, LGPL-3.0, MPL-2.0 |
| 🔴 | 强 Copyleft | GPL-2.0, GPL-3.0 |
| ❌ | 病毒型 / 有问题的 | AGPL-3.0, SSPL, BSL-1.1, Commons-Clause |
## 安装说明
### 一行命令 (macOS / Linux)
```
curl -fsSL https://install.codelake.dev/licscan/install.sh | sh
```
将最新的稳定版本安装到 `/usr/local/bin/licscan`。可以通过以下方式覆盖:
- `LICSCAN_VERSION=v0.11.0` — 指定特定版本
- `LICSCAN_INSTALL_DIR=$HOME/.local/bin` — 安装到其他位置(无需 sudo)
### Homebrew (macOS, Linux)
```
brew install codelake-dev/tap/licscan
```
### Go 安装
```
go install github.com/codelake-dev/licscan/cmd/licscan@latest
```
### 手动下载
针对 Linux、macOS 和 Windows(amd64 + arm64)的预编译二进制文件附在每个 [GitHub Release](https://github.com/codelake-dev/licscan/releases) 中。
```
# macOS (Apple Silicon)
curl -L -o licscan https://github.com/codelake-dev/licscan/releases/latest/download/licscan-darwin-arm64
chmod +x licscan && sudo mv licscan /usr/local/bin/
# Linux (x86_64)
curl -L -o licscan https://github.com/codelake-dev/licscan/releases/latest/download/licscan-linux-amd64
chmod +x licscan && sudo mv licscan /usr/local/bin/
```
Windows 用户:从发布页面下载 `licscan-windows-amd64.exe` 并将其添加到你的 PATH 中。
## 快速开始
```
# 交互式设置 policy + CI workflow
licscan init
# 扫描当前目录
licscan scan .
# 扫描特定项目
licscan scan ~/code/my-project
# 选择输出格式
licscan scan . --format json
licscan scan . --format html > report.html
licscan scan . --format cyclonedx > sbom.json
licscan scan . --format sarif > results.sarif
licscan scan . --format junit > report.xml
# 在 CI 中运行 — 发生 policy 违规时以 exit 1 退出
licscan scan . --ci
# 生成符合 EU CRA 的 SBOM
licscan scan . --cra
# 生成 THIRD_PARTY_LICENSES 文件
licscan notice . --output THIRD_PARTY_LICENSES
# 自更新到最新版本
licscan update
```
## 命令
### `licscan scan [path]`
扫描目录树以查找依赖项许可证。
| 参数 | 默认值 | 描述 |
|---|---|---|
| `--format`, `-f` | `table` | 输出格式:`table`、`json`、`html`、`cyclonedx`、`spdx`、`markdown`、`sarif`、`junit` |
| `--ci` | `false` | CI 模式 — 遇到策略违规或许可证不兼容时返回非零退出码 |
| `--cra` | `false` | 输出符合 EU CRA 标准的 SBOM (PDF + JSON) |
| `--output` | `./licscan-cra-evidence` | `--cra` 产物的输出目录 |
### `licscan init [path]`
交互式设置向导。生成:
- **`.licscan.yml`** — 许可证策略(拒绝/警告列表、项目许可证、CRA 制造商/产品元数据)
- **`.github/workflows/licscan.yml`** — CI 工作流(违规即失败、PR 评论、SARIF 上传、CRA 证据)
未经确认,绝不覆盖现有文件。
### `licscan notice [path]`
生成一个列出所有依赖项及其许可证的 `THIRD_PARTY_LICENSES` / `NOTICE` 文件,按生态系统和包名排序。许多开源许可证要求你在二进制文件旁附带发布归属声明。
| 参数 | 默认值 | 描述 |
|---|---|---|
| `--output`, `-o` | stdout | 输出文件路径 |
| `--project-name` | 自动检测 | 头部的项目名称 |
### `licscan update`
自更新程序。检查 GitHub 上的最新版本,并从 CDN 就地替换当前二进制文件。
| 参数 | 默认值 | 描述 |
|---|---|---|
| `--check` | `false` | 仅检查更新,不执行安装 |
### `licscan about`
打印横幅、版本和归属信息。
### `licscan --version`
打印版本号、commit hash 和构建日期。
### `licscan --help`
打印任何命令的帮助文本。也适用于子命令:
```
licscan scan --help
licscan init --help
licscan notice --help
```
## 策略引擎
在你的项目根目录下放置一个 `.licscan.yml`,以定义 `--ci` 应该拒绝或警告的内容:
```
project_license: MIT
deny:
- AGPL-3.0
- SSPL-1.0
- GPL-2.0
warn:
- GPL-3.0
- LGPL-3.0
allow_exceptions:
- package: some-gpl-lib
reason: "only used in tests, never bundled"
```
### 许可证兼容性检查
当设置了 `project_license`(或从你的 `LICENSE` 文件中自动检测到)时,licscan 会根据兼容性矩阵检查每一个依赖项。MIT 项目中的 GPL 依赖会被标记为 `incompatible`(不兼容),并在 CI 模式下被视为拒绝级别的违规。豁免的依赖项永远不会被覆盖。
当 `licscan scan . --ci` 在 CI pipeline 中运行时:
- 发现任何 `deny`(拒绝)许可证 → **exit 1**(并将违规的包打印到 stderr)
- 发现任何 `warn`(警告)许可证 → 报告 `⚠ warn` 结论,exit 0
- 发现列在 `allow_exceptions` 下的包 → 标记为 `○ exempt`(豁免),exit 0
如果不存在 `.licscan.yml`,则应用内置的默认策略:拒绝 GPL / AGPL / SSPL / BSL / Commons-Clause / Elastic-2.0;警告 LGPL / MPL / EPL / CDDL / EUPL;允许宽松型许可证 (MIT / Apache / BSD / ISC / …)。
## CI 集成
### GitHub Actions
推荐的方式是使用官方的 **[`codelake-dev/licscan-action`](https://github.com/codelake-dev/licscan-action)** — 它可以在一步内完成安装二进制文件、扫描仓库、以 PR 评论形式发布 Markdown 报告,并将报告作为 workflow 产物上传:
```
on: [pull_request]
jobs:
licenses:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: codelake-dev/licscan-action@v1
```
请参阅 [action README](https://github.com/codelake-dev/licscan-action#readme) 以获取所有输入项(`version` 固定、`path`、`cra`、`fail-on-violation`、`pr-comment`、...)和方案(发布时的 CRA 归档、通过 outputs 实现的自定义逻辑)。
如果你更喜欢手动配置 CLI:
```
- name: License compliance
run: |
curl -fsSL https://install.codelake.dev/licscan/install.sh | sh
licscan scan . --ci --format markdown
```
### GitLab CI
```
license_scan:
image: alpine:latest
script:
- apk add --no-cache curl tar
- curl -L https://github.com/codelake-dev/licscan/releases/latest/download/licscan_Linux_x86_64.tar.gz | tar xz
- ./licscan scan . --ci
artifacts:
when: always
reports:
cyclonedx: sbom.json
paths:
- sbom.json
```
## Markdown 报告 (PR 评论 / README)
```
licscan scan . --format markdown
```
生成 GitHub 风格的 Markdown 报告 — 将其粘贴到 PR 评论、issue 正文、README 或 Slack 消息中。包含内容:
- 按风险级别汇总的表格(带有 emoji 标记)
- 按风险降序排列的完整依赖表
- 当依赖项数量超过 30 时自动折叠(``),使庞大的 lockfile 在 PR 线程中保持可读性
- 当生效了 `.licscan.yml` 时,会添加 `Verdict` 列和 `## Policy violations` 部分
典型的 CI 代码片段(将报告作为 PR 评论发布):
```
licscan scan . --format markdown > /tmp/report.md
gh pr comment "$PR_NUMBER" --body-file /tmp/report.md
```
## SBOM 导出
`licscan` 生成两种行业标准格式的 SBOM:
```
licscan scan . --format cyclonedx > sbom.cdx.json # CycloneDX 1.5
licscan scan . --format spdx > sbom.spdx.json # SPDX 2.3
```
这两种格式都包含规范的 PURL(`pkg:golang/...`、`pkg:npm/...` 等),并被主流的漏洞扫描工具(Trivy、Grype、Snyk)和依赖跟踪平台(Dependency-Track、FOSSA、DependencyHub)所接受。CycloneDX BOM 序列号是稳定的 RFC 4122 v4 UUID;SPDX 文档命名空间是每次扫描唯一的 URI。
### SARIF (GitHub Code Scanning)
```
licscan scan . --format sarif > licscan.sarif.json
```
通过 `actions/upload-sarif` 上传到 [GitHub Code Scanning](https://docs.github.com/en/code-security/code-scanning),以便在 Security 标签页中显示许可证违规。只有 `warn` 和 `deny` 的发现会被显示 — 宽松型依赖将被省略。
```
- uses: codelake-dev/licscan-action@v1
- run: licscan scan . --format sarif > results.sarif
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
```
### JUnit XML (Jenkins / GitLab CI / Azure DevOps)
```
licscan scan . --format junit > licscan-report.xml
```
每个依赖项都是一个 testcase。Warn/deny/incompatible 的结论会被视为测试失败。兼容任何接收 xUnit 风格报告的 CI 系统。
## NOTICE 文件生成
```
licscan notice . --output THIRD_PARTY_LICENSES
```
生成一个列出每个依赖项及其许可证的 THIRD_PARTY_LICENSES 文件。许多开源许可证(Apache-2.0、BSD、MIT)要求你在重新分发时包含归属声明。
## EU CRA 合规模式
欧盟网络弹性法案(Regulation (EU) 2024/2847)要求“包含数字元素的产品”的制造商维护一份具有特定元数据的机器可读 SBOM(第 13 条,附录 I §1(2)(s))。`--cra` 可以在一次扫描中同时生成 CycloneDX 1.5 JSON SBOM **和** 可供监管机构查阅的 PDF:
```
licscan scan . --cra
# → ./licscan-cra-evidence/cra-sbom.cdx.json
# → ./licscan-cra-evidence/cra-evidence.pdf
```
自定义输出目录:
```
licscan scan . --cra --output ./compliance/
```
### 制造商元数据
在 `.licscan.yml` 中设置所需的 CRA Article 13(2) 生产者身份:
```
manufacturer:
name: Acme GmbH
email: security@acme.example
url: https://acme.example
country: DE
product:
name: my-app
version: 1.2.3
category: important
support_lifecycle_end: "2031-05-24"
```
如果没有制造商信息块,证据依然会生成,但 PDF 封面会带有警告,提示提交给监管机构需要填写那四项必填字段。
### 生成的内容
**`cra-sbom.cdx.json`** — 带有 CRA 特定扩展的 CycloneDX 1.5 SBOM(机器可读):`metadata.manufacturer`、`metadata.supplier`(licscan 本身)、`metadata.lifecycles.phase=operations`,以及包含法规、条款、附录、制造商国家、产品类别和支持生命周期结束时间(作为 `eu-cra:*` 命名空间属性)的 `metadata.properties[]`。
**`cra-evidence.pdf`** — 面向监管机构的摘要(人类可读):
- 包含制造商 + 产品 + 扫描元数据 + 关于此文档声明的封面
- 许可证风险汇总表(按风险级别的计数,颜色编码)
- 按风险降序排列的完整依赖清单
## 从源码编译
需要 Go 1.22 或更高版本。
```
git clone https://github.com/codelake-dev/licscan
cd licscan
# 运行所有测试
make test
# 构建本地 binary
make build
# 安装到 $GOPATH/bin
make install
# 为所有发布目标进行交叉编译(需要 goreleaser)
make release-dry-run
```
不使用 `make`:
```
go test ./...
go build -o ./bin/licscan ./cmd/licscan
go install ./cmd/licscan
```
### 项目布局
```
licscan/
├── cmd/licscan/ # CLI entry point (main package)
├── internal/
│ ├── cli/ # Cobra command tree (scan, init, notice, update, about)
│ ├── scanner/ # Core scan engine
│ │ ├── detectors/ # Package-manager detectors (gomod, npm, composer, …)
│ │ ├── format/ # Output formatters (table, json, html, sarif, junit, …)
│ │ └── policy/ # Policy engine + license compatibility matrix
│ ├── version/ # Build-time metadata (ldflags-injected)
│ └── banner/ # ASCII logo + attribution
├── example-outputs/ # Sample output for every format
├── .github/workflows/ # CI + release pipelines
└── .golangci.yml # Lint config
```
## 贡献指南
欢迎提交 Issues 和 PR — 请参阅 [CONTRIBUTING.md](CONTRIBUTING.md) 了解贡献工作流、提交约定以及如何在本地运行完整的测试套件。
## 许可证
Apache License 2.0 — 完整文本请参阅 [LICENSE](LICENSE),第三方归属说明请参阅 [NOTICE](NOTICE)。
**LicScan** · 由 [codelake Technologies LLC](https://codelake.dev) 提供。Akyros Labs 旗下品牌。
标签:DevSecOps, EVTX分析, Go, LNA, Ruby工具, SBOM, 上游代理, 依赖管理, 开源合规, 日志审计, 硬件无关, 许可证扫描