BargLabs/cejel
GitHub: BargLabs/cejel
Cejel 是一款离线、免注册的 CLI 工具,通过对代码仓库的工程实践特征进行确定性评分来生成可共享的信任证书和徽章。
Stars: 0 | Forks: 0
# cejel
[](https://github.com/BargLabs/cejel/releases/latest)
[](./LICENSE)
Cejel(*"SEH-jel"*)—— 为你的代码库提供的信任证书。
免费、离线、免注册的 CLI 工具,它为那些决定你是否信任一个代码仓库的工程特征(如测试、密钥、隔离、宣传与实际是否相符、CI/审计规范)进行评分,并打印出信任证书和徽章。当大量代码由 AI 编写时,它显得尤为重要:因为这正是你无法仅凭肉眼评估信任度的时候。它基于确定性的、无 LLM 的评分核心构建——免费路径完全不发起任何网络调用,也不需要任何账户。
Cejel 并非另一个与你当前正在使用的扫描器竞争的单点扫描工具——它是开源的、可移植的、离线的信任证书,能够将它们聚合起来。通过管道传入兼容 SARIF 的输出(MunaTrust, Snyk, Semgrep, CodeQL, Codex)以及 OpenSSF Scorecard,你就可以在所有这些工具之上获得一份可共享的证书和徽章。请参阅下文的“聚合你的扫描器”。
## 安装
无需账户,无需密钥,无需注册。
**单文件二进制程序。** 仅需一个文件。不需要 Node、npm、`node_modules`,什么都不需要安装。
```
curl -fsSL https://github.com/BargLabs/cejel/releases/latest/download/cejel-$(uname -s)-$(uname -m) -o cejel
chmod +x cejel
./cejel .
```
**不要轻易相信离线的声明——请亲自验证。** 关闭你的网络,然后运行该二进制程序。它无论如何都会对你的仓库进行评分并为你生成证书。这就是产品的全部核心,你可以在十秒内证伪它:
```
# 关闭 Wi-Fi,或者:
docker run --rm --network=none -v "$PWD:/w" -w /w -v "$PWD/cejel:/cejel:ro" debian:stable-slim /cejel .
```
**npm。**
```
npx @cejel/cejel .
```
**GitHub Action** — 为每个 PR 评分并发布徽章:
```
- uses: BargLabs/cejel/action@v1
with:
min-score: "2.5" # optional: fail the build below this
```
**从源码构建** — 它是 AGPL 授权且离线运行的,所以阅读源码本身就是核心目的:
```
git clone https://github.com/BargLabs/cejel && cd cejel
pnpm install && pnpm build
node dist/index.js .
```
已发布的二进制程序:`cejel-Darwin-arm64`、`cejel-Linux-x86_64`。Homebrew tap 和其他架构的构建正在进行中;由于目前尚不存在,因此未在此列出。
## 排行榜
本仓库提供了 [Cejel OSS 信任排行榜](./leaderboard/leaderboard.md):对整个语料库进行了评分并公开发布——包括顶级的 OSS 项目、Cejel 本身,以及构建 Cejel 的私有工作室 monorepo——并在 [`leaderboard/reports/`](./leaderboard/reports/) 下为每一行提供了对应的仓库证据报告。该榜单同时也托管在 [cejel.dev](https://cejel.dev)。榜单上的每一个分数都是由 `npx @cejel/cejel .` 所使用的同一个密封的公开评分器生成的——查看报告中打印的源码 commit,运行该工具,你就会得到这个数字。一个必要的检查机制会对语料库中的每一行执行相同的操作,并比较分数、结论、测量的覆盖率和证据。没有任何私有域名收集器会为任何已发布的分数(包括我们自己的)做出贡献;没有任何例外。
### 脱敏政策
只有当读者可以核对时,路径才会被发布。榜单上的每一个公开仓库都会在每一个制品的各个位置引用完整的证据路径和行号——一份你无法打开其证据的证书算不上是证据。两个私有仓库的条目(本 monorepo 自身的透明度条目,以及包含在其中的 Cejel 自身源码子包)在任何地方、任何字段或格式中都不会引用源码路径——但是发现本身、它的维度、状态、分数和内容哈希值始终会被保留;仅仅是位置被隐藏了,统一标记为“路径已隐藏 —— 私有仓库”。脱敏去除的是一个位置,而不是事实:私有仓库如果未能通过自身的检查,依然会以其名义显示在其证书上。v3 仓库扫描器将 B1 和 B5 标记为对所有仓库(包括我们自己的)都不适用;它不接受针对它们的结构化基础证据。对于其他 rubric 输入,它们仍然保持定义,而仓库排名在排除这两项时采取 fail-closed(失败即关闭)机制。不会基于公开扫描器无法收集的证据对任何人进行评分。
### 已知的误报(在发布前已修复)
将一个 rubric 与真实的、顶级的仓库进行校准会暴露出一些错误;这个记录是信任声明的一部分,而不是需要掩盖的东西。有两个维度因为缺乏可评级的基准面(而非真正的弱点)而产生了惩罚性的分数,这两个问题都已修复:
Django 因为使用版本范围而非精确锁定版本而在依赖项规范方面被标记为严重——这对于库(而不是应用)来说是正常的、刻意做法;现在 rubric 会根据符合原型特征的标准来对依赖项规范进行评分。OSSF Scorecard —— Google 自己的供应链安全审计工具—— 因为通过 GitHub Releases 而不是提交 `CHANGELOG.md` 来发布发行说明,而在审计轨迹完整性方面被标记为严重;现在,一个没有可评级审计基准面的仓库会返回“数据不足”(从综合评分中排除),而不是得到惩罚性的分数。该榜单还在每一行发布了测量覆盖率指标:分数仅反映其*已测量*的维度,如果某行的评估维度不足其适用维度的一半,则会显示为未排名,而不是与证据更充分的行进行排序对比。
## 用法
```
./cejel .
```
使用合理的默认值对当前目录进行评分:无需任何标志,无需注册,完全离线。
它会打印一份简洁的终端证书,并写入 `.cejel/` 目录:
- `report.json` —— 完整的结构化报告
- `certificate.html` —— 独立的 HTML 证书(无外部资源依赖)
- `badge.json` —— [shields.io endpoint](https://shields.io/badges/endpoint-badge) payload
- `badge.svg` —— 静态的、独立的信任分数徽章
- `summary.json` —— 精简摘要(分数、结论、核心发现)
### 标志(Flags)
- `` —— 要评分的仓库(默认:当前目录)
- `--out-dir ` —— 写入报告/证书/徽章文件的目录(默认:`.cejel`)
- `--min-score ` —— 如果总分低于 `n` (0–4) 则以非零状态退出;由 GitHub Action 的可选阈值门控使用
- `--ingest ` —— 将另一个扫描器的输出合并到评分中(可重复使用)。接受 SARIF、OpenSSF Scorecard JSON 或通用的 Cejel 外部信号格式——格式将被自动检测。请参阅下文的“聚合你的扫描器”。
- `--quiet` —— 抑制终端证书打印(文件仍会被写入)
## 支持的语言
Cejel 读取的是仓库的文件树,而不是它的字节码——它需要识别文件的源码扩展名才能对其进行评判。它并不支持所有语言,而且它会诚实地告知这一点,而不是瞎猜:
- **深度建模** —— JS/TS、Python:测试检测、覆盖率以及宣传与实际是否相符的检查都是专门为这些生态系统量身定制的。
- **部分建模** —— Go、Rust、Java、Ruby、PHP、C#、C/C++、Swift、Kotlin、Dart、Elixir、Scala:会被识别为源码并在与语言无关的维度(CI 规范、依赖项规范、审计轨迹、密钥)上进行评分,但没有针对特定生态系统的测试框架调优。
- **已识别但未建模** —— shell、R、Lua、Julia、Haskell、Terraform、SQL、Perl、OCaml、Clojure、Erlang、Nim、Zig、F#、Groovy:会被计为源码,以免仓库被误判为空,但在三个层级中,其特定生态系统的调优最少。
- **尚未识别** —— 其他生态系统,包括 COBOL、Fortran 和 MATLAB。Cejel 完全不会将这些语言计为“源码”:一个没有任何已识别扩展名文件的仓库将获得 `unrecognised_ecosystem`(未识别的生态系统)的原型特征、明确的 `insufficient_data`(数据不足)状态,并且**没有结论**——绝不会给出一个自信的数字分数,也绝不会仅仅因为 cejel 无法读取该语言而给出“未验证”的字眼。证书会明确说明 11 个维度中哪些被测量了,哪些没有被测量。
这个列表将会增长。但它永远不会变成“支持任何代码库”——这种声明是解析器无法兑现的承诺,而且一个诚实的支持矩阵,远比一句在别人第一次运行它遇到不支持的仓库时就会被代码本身打脸的营销口号有价值得多。
## 聚合你的扫描器
Cejel 不会与你的 AI 代码扫描器(MunaTrust、Snyk、Semgrep、CodeQL、Codex,或者是任何在 CI 中运行的工具)竞争——它是建立在这些工具之上的。使用 `--ingest` 传入扫描器的输出,Cejel 就会将这些发现整合到同一个经过 rubric 评分的、离线的信任证书中,并将贡献工具在证书和报告中作为出处显示:
```
./cejel . --ingest munatrust.sarif --ingest scorecard.json
```
或者将文件放入 `.cejel/inputs/` 目录下,它们就会被自动拾取,不需要任何标志:
```
mkdir -p .cejel/inputs
cp munatrust-results.sarif .cejel/inputs/
./cejel .
```
外部发现只会*向下*调整维度分数,并且调整量是有上限的——它们是对原生仓库扫描的增强,绝不会替代它。每一个被摄入的文件都会在 `certificate.html`、`report.json`(`consumedSignals`)和终端输出(“包含来自以下工具的发现:...”)中注明名称,因此该证书读起来就像是一个可见的聚合体,而不是一个黑盒。
扫描器输出的三种摄入方式:
1. **SARIF** —— 任何发出 SARIF 2.1.0 格式的工具(Semgrep、CodeQL、大多数商业 SAST/AI 代码扫描器)都无需配置即可工作;`--ingest` 会自动检测 `runs` 数组。
2. **OpenSSF Scorecard** —— `scorecard --repo=... --format=json > scorecard.json`,然后 `--ingest scorecard.json`;通过其 `checks` 数组进行自动检测。
3. **通用 JSON** —— 对于不发出上述两种格式的工具,将其输出映射为下面所示的最小结构(如果格式需要真正的解析,可以参照
[`scorecard-adapter.ts`](../witan/src/scorecard-adapter.ts) 编写一个小适配器):
{
"tool": "my-scanner",
"signals": [
{
"dimension": "A2",
"weight": 0.7,
"findings": [
{
"ruleId": "hardcoded-secret",
"severity": "critical",
"message": "Hardcoded API key detected.",
"location": "src/config.ts:10"
}
]
}
]
}
`dimension` 是 Witan rubric 标准的 ID 之一(`A1`-`A5`,`B1`-`B6`);`weight`(0–1,默认为 `0.5`)限制了该信号能在多大程度上影响该维度;`severity` 为 `critical` | `warning` | `info`;`location` 为可选项。
## 展示信任徽章
Endpoint JSON(将 `badge.json` 托管在任何静态位置——如仓库文件、gist、GitHub Pages——并让 shields.io 指向它):
```

```
或者直接提交/链接静态 SVG:
```

```
## GitHub Action
请参阅 [`action/action.yml`](./action/action.yml) —— 在 `push`/`pull_request` 时运行 Cejel,将分数和核心发现发布到作业摘要中,并可选择在低于可配置的 `min-score` 阈值时使检查失败。评分步骤不进行任何网络调用,也不需要任何密钥。
```
- uses: BargLabs/cejel/action@v1
with:
min-score: '2.5' # optional; omit to never fail the check
```
## MCP server(面向 agents)
相同的包还发布了第二个可执行文件 `cejel-mcp`——一个基于 stdio 的轻量级 MCP(Model Context Protocol)server,因此任何 MCP 客户端(Claude Code, Cowork, Cursor, Codex)都可以将其作为一次工具调用来请求信任证书。它封装了与 CLI 完全相同的扫描——相同的分数、相同的结论——并且通过仓库的 `smithery.yaml` 在 Smithery 上进行了 listing。
将其添加到 MCP 客户端配置中:
```
{
"mcpServers": {
"cejel": {
"command": "npx",
"args": ["-y", "--package=@cejel/cejel", "cejel-mcp"]
}
}
}
```
该 server 暴露了一个工具和两个资源:
- `scan` —— 输入 `{ path, format? }`;对位于 `path` 的仓库进行评分,并以 JSON 格式返回信任证书(`format: "summary"` 是默认值,即精简摘要;`format: "json"` 是完整报告,与 CLI 的 `report.json` 完全相同)。
- `cejel-cejel://last-scan/certificate.html` 和 `cejel-cejel://last-scan/badge.svg` —— 最近一次扫描的 HTML 证书和 SVG 徽章(URI scheme 源自 npm 包名,`@cejel/cejel` → `cejel-cejel`)。
与 CLI 一样,通过 MCP 进行评分也是完全离线的:不进行网络调用,不收集遥测数据,不需要注册,并且 server 写入任何文件。
## “离线”在这里的含义
对仓库进行评分——即 `cejel .` 命令本身,以及 Action 的评分步骤——不会发起任何网络调用:无遥测,无注册,无模型调用。首次获取 `@cejel/cejel` 包(就像任何通过 npm 分发的 CLI 一样,包括该 Action 自身的依赖项安装)确实需要网络;这是一次性的安装成本,不属于评分保证的一部分。
## 公开排行榜:我们脱敏了什么,排除了什么,以及我们在哪里犯了错
我们发布了一个信任榜单,对我们自己以及一系列知名的开源仓库语料库进行评分。在别人的代码上运行排行榜要求我们必须准确说明它是如何运作的,所以以下就是全部内容。
**我们脱敏了什么,以及基于什么原则。** 一个原则:*只有当你能够核对时,路径才会被发布。* 对于公开仓库,每一个证据路径和行号都会被完整引用——一份你无法打开其证据的证书算不上是证据。对于私有仓库(我们自己的),**在任何地方、任何字段或格式中,都不会引用任何源码路径**;一个无法验证的路径不会告诉你任何你可以核对的信息,反而白白暴露了我们的文件树。脱敏去除的是一个**位置**,而不是**事实**:发现本身、它的维度、状态、分数和内容哈希值都会保留。如果路径被隐藏,你会看到明确的说明。这是在结构上强制执行的——公开的制品是从经过过滤的数据构建而成的,而不是先渲染再擦除——任何试图输出私有路径的构建都会失败,而不是被发布出去。
**我们在排名中排除了什么。** v3 仓库扫描器不会针对仓库输入(包括我们自己的)评估 B1(调度轨迹完整性)或 B5(已验证的学习轨迹):两者在仓库证书中始终是*不适用的*。它们在针对结构化基础证据的 rubric 中仍然是有定义的,但该扫描器不接受此类证据。排名采取 fail-closed(失败即关闭)机制排除了这两个维度,包括当它读取旧版或独立生成的结构化报告时也是如此。我们既不会基于公开扫描器无法收集的证据来给你评分,也不会因为一些你无法反驳的证据而给我们自己加分。
**我们在哪里犯了错。** 将这个 rubric 与真实的仓库进行校准——并且像一个陌生人一样运行这个榜单本身——暴露了我们自己工具中的七个错误,这些错误都在发布日之前(或在一个案例中是在发布日当天)被发现并修复了。我们将它们列出来,因为一个从未犯过错的评分工具就是一个从未被检查过的评分工具:
- **Django,在依赖项规范方面被误判为严重。** 我们将针对应用的期望套用到了一个库上。现在原型特征会控制该维度的评分。
- **OpenSSF Scorecard,在审计轨迹方面被误判为严重。** 我们给 Google 自己的审计工具打上了审计不足的标签。该维度在评估“这东西有多好?”之前,缺乏一个“这里到底有没有可以评级的对象?”的门控;现在它已经有了。
- **在榜单的早期构建版本中,17 个仓库中有 12 个被悄悄丢弃了**,但系统却报告了成功。生成器总是会在不知不觉中丢失数据行。现在它会断言语料库中的每一个仓库都已被处理——无论是已排名、未排名还是出错——否则就会报错。
- **低覆盖率的仓库被当成完全测量的仓库进行排名。** 现在的信心基准线会在发布它们时不对其进行排名,而不是暗示一种我们本不具备的精确度。
- **A1 的定期工作流检查将我们自己内部 QA agent 的文件名硬编码**为了它的定义,而不是它实际测量的概念。从构造上来说,它对外部所有仓库都是无效的——这是一条伪装成通用规则的主场规则。它现在检测的是*形态*(即一个运行验证套件的 cron 定时工作流,以及其结果是持久发布的,还是仅仅交给了一个临时的 CI 制品);我们自己内部的每夜 QA 工作流只是该形态的一个被识别的实例,而不是它的定义。
- **我们的榜单和我们自己的证书在四个仓库的标题分数上存在 0.1 的分歧**——两种连贯的基础(榜单公平的跨仓库排名基础,以及每个证书自身的维度基础),却都印上了同一个词:“Overall”。我们在发布日发现了这个问题并进行了修复:现在“Overall”在它出现的所有地方——榜单、证书、徽章、报告和 JSON——在字节级别上都是完全一致的;而排名基础(在确实存在差异的地方)现在有了自己单独且明确标注的列,不再借用同一个名字。
- **我们自己的这一行使用了一个其他人无法运行的评分路径。** 榜单生成器可以在公开扫描之后添加内部收集器,因此它那令人安心的收集器黑名单并不像它所声称的那样是不变的。Rubric v3 移除了这第二条路径:现在语料库中的每一行都通过相同的密封公开评分器进行处理,每一个外部源都被固定到一个 commit,并且有一个必需的防护机制会对每一行重新评分,比较分数、结论、覆盖率和证据。这一诚实的更正将 Alfred 的 Code 分数从 2.5 移到了 2.4,A5 从 2.9 移到了 2.4。这虽然没那么讨喜,但却更值得信赖。
每一个都是由*我们*造成的信任失败——关于别人代码的误报、悄悄的遗漏、不一致的展示,或者是仅限内部使用的评分路径——我们宁愿让你知道这一点,也不愿你后来自己发现它。如果你认为榜单对你的仓库评分有误,请提一个 issue——一个无法在公开场合被纠正的 rubric 是没有资格被公开发布的。
**任何 rubric 的更改都不会悄悄改变你的分数。** 评分行为的每一次更改都需要提升 `WITAN_RUBRIC_VERSION` 版本号,并在 [`docs/leaderboard/RUBRIC_CHANGELOG.md`](../../docs/leaderboard/RUBRIC_CHANGELOG.md) 中发布全语料库级别的变更前后差异——每一个仓库的分数、结论和排名,并在结果为“没有仓库发生变动”时明确声明。任何更改评分行为却未同时执行这两项操作的构建都会失败;请参阅该文件中针对上述主场规则修复的 `v2` 条目,这是以此方式记录的第一个 rubric 变更。
## 许可证
`cejel` 是免费的,并根据 [AGPL-3.0-only](./LICENSE) 协议授权,属于 copyleft 性质:你分发或作为网络服务运行的任何修改版本,都必须在相同条款下公开其源码。如果团队需要在不受这些 copyleft 义务限制的情况下使用或修改 `cejel`,我们提供商业许可证。
标签:LNA, MITM代理, 云安全监控, 安全合规, 文档结构分析, 网络代理, 自动化攻击, 静态分析