epheterson/assay
GitHub: epheterson/assay
这是一个通过AI审查GitHub仓库发布差异、自动判断其安全意图的监控工具,用于防范软件供应链攻击。
Stars: 1 | Forks: 0
# 检测
监控 GitHub 仓库的发布。每次新发布时,运行一系列检查(URL 清单、提交者差异等),由 LLM 判断差异是否符合声明的意图,并将结构化判定结果发送至 **电子邮件 + GitHub Issues**。
适用于依赖自动更新软件的情况——侧载应用、npm 包、Homebrew 安装脚本、容器镜像——并希望在供应链攻击发生时引入人工审核机制。
## 历史
[**LEDGER.md**](LEDGER.md) — assay 已给出的每个判定结果的绿/红名单,按最新排序,附有每个发布的链接。
## 判定结果
每个发布都会得到以下之一:
| 判定结果 | 含义 | Issue 状态 |
|---|---|---|
| ✅ **clean** | 差异与声明意图一致。无值得您关注的异常。 | 自动关闭 |
| ⚠️ **review** | 存在值得人工审查的异常——新提交者、新 URL 等。 | 保持打开 |
| 🚨 **blocked** | 高置信度问题。请勿自动更新。 | 保持打开 |
状态存储在 assay 仓库自身的 GitHub Issues 中。每个判定结果会打开一个 Issue,标签为 `assay:{owner}/{repo}` + `verdict:{class}`。带有该标签的最新 Issue *即* 当前状态——原子化、可审计、无冲突,并可通过 GitHub 移动应用原生推送到您的手机。
## 工作原理
```
every 30 min cron
│
▼
┌─────────────────────────┐
│ poll upstream releases │ cheap; no LLM, no download
└────────────┬────────────┘
│ new tag?
▼
┌────────────────────────────────────────┐
│ run check modules (committer_diff, │ expensive; only fires
│ url_inventory, …) │ on new release
└────────────────────┬───────────────────┘
▼
┌────────────────────────────────────────┐
│ judge: GitHub Models LLM call, │
│ produces structured verdict │
│ ★ rule-based override: │
│ hard_flag from any module │
│ forces verdict ≥ review │
└────────────────────┬───────────────────┘
▼
┌────────────────────────────────────────┐
│ write GH issue (state + audit log │
│ + native push notification) │
│ send email │
│ commit verdict JSON to repo │
└────────────────────────────────────────┘
```
## 模块
| 模块 | 检查内容 | 硬性标记条件 |
|---|---|---|
| `committer_diff` | 在此时间窗口内新增的作者 | 任何首次提交者 |
| `url_inventory` | 二进制文件或源代码中新增/移除的主机名 | 新主机不在允许列表中 |
(路线图:`dependency_diff`、`file_tree_diff`、`entitlement_diff`、`framework_diff`、`secret_scan_diff`、`osv_scan`。)
## 评判器
调用 **GitHub Models** 端点 `https://models.github.ai/inference/chat/completions` — 对公开仓库免费,除工作流内置的具有 `models: read` 权限的 `GITHUB_TOKEN` 外,无需其他 API 密钥。默认模型:`openai/gpt-4o-mini`。使用 `response_format=json_object` 输出结构化数据。
如果 LLM 调用失败或设置了 `USE_FAKE_JUDGE=1`,则回退到启发式判定。**任何模块的硬性标记都会强制判定结果 ≥ review** — LLM 的职责是*解释*,而非*把关*。
## 参考用例:Reddit 的 Apollo
Reddit 的 Apollo 于 2023 年 6 月停止运营。一个社区分支([`JeffreyCA/Apollo-ImprovedCustomApi`](https://github.com/JeffreyCA/Apollo-ImprovedCustomApi))使其保持可用;[`Balackburn/Apollo`](https://github.com/Balackburn/Apollo) 通过一个 AltStore 源构建并分发 IPA 文件。
这涉及 5 个以上的信任节点(调整插件作者、分发者、AltStore 源、AltServer、您的开发者证书)。Apple 的 App Store 审查机制在设计中已被移除。`assay` 在这条链条前端充当看门人。
参见 [`examples/apollo/`](examples/apollo) 和 [`.github/workflows/assay-apollo.yml`](.github/workflows/assay-apollo.yml)。
## 添加新的上游仓库
1. 在 `.github/workflows/assay-{name}.yml` 中放置一个工作流,参照 `assay-apollo.yml` 的格式。
2. (可选)在 `examples/{name}/allowlist.json` 中放置一个列出预期主机的允许列表文件。
3. 推送代码。定时任务会捕获它;首次运行会写入一个基线 Issue。第二次新发布时会写入真正的判定结果。
## 通知
| 通道 | 设置方式 |
|---|---|
| **GitHub 原生推送** | 在 github.com 订阅您的 `assay` 仓库分支。每个判定结果都会打开一个 Issue → 通过 GitHub 移动应用即时推送。已关闭的 Issue = 清洁判定;打开的 Issue = 需要关注。 |
| **电子邮件** | 添加 `GMAIL_USERNAME` + `GMAIL_APP_PASSWORD` 仓库密钥。详见下文。 |
| **Webhook** | 路线图规划中。 |
### 设置 Gmail 电子邮件(2 分钟设置)
1. 前往 https://myaccount.google.com/apppasswords(需要账户启用两步验证)
2. 生成一个标记为 "assay" 的应用密码 — 复制 16 位字符串
3. 在仓库中:设置 → 密钥和变量 → 操作 → 新建仓库密钥
4. 添加 `GMAIL_USERNAME` = your-gmail-address@gmail.com
5. 添加 `GMAIL_APP_PASSWORD` = 16 位应用密码(无空格)
6. 下一个判定结果触发时,将向 `.github/workflows/assay-apollo.yml` 中 `to:` 地址发送一封电子邮件。
## 为何不直接使用 {工具}?
| 现有工具 | 覆盖范围 | `assay` 的补充 |
|---|---|---|
| OpenSSF Scorecard | 仓库卫生元数据 | 每次发布的行为差异 |
| Dependabot / OSV-Scanner | 声明依赖中的已知 CVE | 新颖变更;二进制文件 |
| Trufflehog / Gitleaks | 泄露的密钥 | 带 AI 评判器的行为差异 |
| Socket.dev | npm/pypi 供应链 | 与生态系统无关 |
| Sigstore / SLSA | 构建来源 | "二进制文件做什么?"的判断 |
`assay` 的定位是:**"监视此上游仓库的发布,通过 AI 根据声明意图评判差异,并根据判定结果把关下游使用。"**
## 许可证
MIT。祝您使用愉快。
标签:AI代码审查, GitHub Issues集成, GitHub仓库监控, URL发现, 供应链信任, 供应链攻击防护, 侧载应用安全, 发布管理, 大语言模型应用, 安全检测, 安全网关, 定时任务, 差异分析, 持续监控, 结构化查询, 自动化安全, 软件供应链, 软件更新监控, 逆向工具, 邮件通知