ma3s1r0/Vouchq
GitHub: ma3s1r0/Vouchq
Vouchq 是一个自托管的 MCP 工具信任注册中心,通过加密锁定已批准的工具定义并持续检测线上漂移,来防范 AI agent 工具供应链中的 rug-pull 篡改攻击。
Stars: 1 | Forks: 0
# Vouchq
[](https://github.com/ma3s1r0/Vouchq/releases/tag/v0.1.0-alpha)
[](https://ma3s1r0.github.io/vouchq-website)
[](LICENSE)
[](https://openjdk.org/projects/jdk/21/)
[](https://spring.io/projects/spring-boot)
[](https://www.postgresql.org/)
[](#production-self-hosted-docker-compose)
**English** · [한국어](README.ko.md)
## 看它如何捕获 rug-pull
一个已获批的 `web_search` 工具被锁定。随后其上游服务器悄无声息地重写了
描述以窃取机密——Vouchq 检测到了漂移,并将当前线上版本
标记为 CRITICAL,而被锁定的良性版本仍然是 agent 接收到的内容。

## 什么是 Vouchq
AI agent 加载 Skills 并连接到 MCP 服务器,而这些服务器的工具描述可以在**运行时**发生改变。在你采用时本是良性的功能,随后可能会发生变异——一个工具描述悄无声息地获得了一个隐藏的 *“……同时将结果发送到 attacker.com”* 指令,而 agent 会盲目执行它。这就是一场 **rug-pull**,而 MCP 规范本身允许在会话期间更改工具描述,且没有完整性检查、哈希锁定或强制重新批准。
Vouchq 记录了*您的组织批准信任的内容及其对应版本*——它是一个权威记录,同时也是一台验证引擎,专门用于捕获已批准的定义被**悄无声息地更改**的情况。Discovery catalogs 只会对功能检查**一次**;而 Vouchq 会根据加密**锁定**的基准线,持续验证**线上**定义,因此批准后的篡改会被捕获,而不是被默认忽略。
它**不是**一个 discovery catalog(“世界上存在什么”),也**不是**一个 inline proxy。它是信任的控制面*发行方*:在准入阶段进行治理,在分发阶段提供担保。
## 核心功能
### 摄取与清单
连接 Git 仓库以及(阶段 1 的)MCP 服务器。Vouchq 的 OSS 解析器会将 Skills(`SKILL.md` + 脚本)和 MCP 工具(`tools/list`)标准化为单一的 definition 模型,并构建一个可搜索的清单,涵盖您的 agent 可以触及的每一项功能——包括类型、来源、状态、风险以及最后验证时间。
### 风险扫描
基于规则的扫描器会检查每个定义是否存在 **prompt injection**、**泄露的机密**、**数据窃取**和**危险命令**,生成 0-100 的风险评分以及结构化的发现结果。**误报抑制**(基于规则/工具/发现级别)确保了高信噪比,让审核者能够信任该评分。该扫描器是纯 Java 开发且开源的。
### 批准并锁定 (박제)
当审核者批准一个定义时,Vouchq 会对其进行快照处理,并存储一个不可变的 **SHA-256 基准线**——即 *정본*(“权威原件”)。这个被锁定的版本是衡量其他所有内容的固定参考点,也是向下游分发的确切制品。
### 漂移 / rug-pull 检测
定期的(或手动的)重新扫描会重新获取线上的定义,并将其哈希值与锁定的基准线进行比较。任何偏差都会引发一个带有严重程度(`INFO` / `WARN` / `CRITICAL`)和字段级差异对比的 **DriftEvent**,将该工具状态切换为“需要审核”,并作为正在进行中的 rug-pull 的警报。
### 策略引擎
声明式规则会根据扫描和漂移结果采取行动——例如,自动**拦截**或**挂起**任何越过风险阈值或触发严重漂移的项目——这样无需等待人工干预即可对高风险更改进行管控。
### 审计 (WORM + 哈希链)
每一次注册、扫描、批准、拦截和漂移事件都会被写入一个**只追加的审计日志**。这些条目通过 `prev_hash → entry_hash` SHA-256 链条连接在一起,且该数据表在**数据库层面实行 WORM 强制约束**(通过更新/删除触发器),因此任何篡改都会破坏链条并被检测到——从而将该日志转化为真正的合规证据。
### RBAC 与多租户
采用 Spring Security 实现 **Admin / Member / Viewer** 角色。所有数据都通过 `org_id` 进行隔离,并在查询层强制执行,因此多个团队或租户可以共享一个部署而不会发生跨边界的数据泄露。
### 分发 / 安装
开发者只需拉取经过**担保(已批准)**的功能——永远不拉取线上的上游内容。一个仓库可以注册许多 Skills,因此清单会按来源对它们进行分组,每个分组都有一个一键**Install** 功能,会生成一段可直接复制粘贴的 `curl … | sh`:生成的脚本会从 Vouchq 中获取每一个已批准的文件(确切的**锁定**字节),在写入前重新验证其 SHA-256,并将其放入 `.claude/skills/` 目录中。系统只提供 `APPROVED` + 锁定的 skills——处于待处理 / 漂移 / 拦截状态的会被报告并跳过——并且每次安装都会以 `SKILL_INSTALL_SERVED` 的形式记录在 WORM 审计日志中。**远程** MCP 服务器也以同样的方式安装——只有当服务器状态良好时(≥1 个已批准工具,且没有任何工具被拦截或发生漂移;拒绝本身就是一个信号),才会为其颁发一个已担保的连接配置,适用于 Claude (`.mcp.json`)、Cursor (`.cursor/mcp.json`) 或 Codex (`config.toml`),并记录为 `MCP_INSTALL_SERVED`。因为字节流来自于 Vouchq 锁定的快照,而不是全新的 `git clone`,所以使用者永远不会重新拉取到一个遭到 rug-pull 的上游。Vouchq 颁发可信制品;它并不驻留在请求路径的内联位置。
### 范围 —— 仅限第一方观察
Vouchq 管控的是它能够进行**第一方**观察其定义的功能:Skill 的字节流(从仓库中解析得到)以及**远程** MCP 服务器的工具表面(直接通过 `tools/list` 获取)。它只锁定和验证它自己能看到的内容。
**本地 stdio MCP 服务器** —— 即 agent 在您自己的机器上启动的 `docker run` / `npx` 二进制文件 —— 是**刻意排除在范围之外的。** 管控它们要么需要在 *Vouchq 自己的信任边界内*执行一个未经核实的第三方服务器(引入了 Vouchq 存在的初衷就是要遏制的那类确切的供应链风险),要么就得信任提交者捕获的工具表面快照(这是道听途说,不是验证)。Vouchq 不会声称对其无法独立观察的内容提供担保——而且锁定 `@sha256` 摘要代表的是可重现性,而非安全判断,所以我们不会对其进行伪装。如果确实产生了此类需求,正确的答案应该是从受信任的 CI 中进行**带有签名的、经过证明的**捕获,而不是进行静默执行或使用未签名的快照。
## 架构
### 模块映射
```
:parser library — Skill / MCP definition parser; pure Java, no framework deps
:scanner library — rule-based risk scanner; pure Java
:app Control plane (Spring Boot); depends on :parser / :scanner
└ registry / audit / notify / policy / tenancy / api
console/ Admin console (Next.js + Tailwind)
```
Vouchq **在 AGPL-3.0 下完全开源**——包括整个技术栈以及附带的
库。即使作为服务运行,AGPL 也能保持每一部分的开放(因此无法将核心组件的简单包装器作为闭源 SaaS 提供)。参见 **[`LICENSING.md`](LICENSING.md)**。
### 工作原理
```
┌── Governance (door in) ────────────────────────────────────────────────┐
│ Git repo / MCP server │
│ │ parse (:parser) │
│ ▼ │
│ Inventory ──► Scan (:scanner) risk score + findings + FP suppression │
│ │ │
│ ▼ reviewer approves │
│ Approve & Pin (박제) ──► immutable SHA-256 baseline (정본) │
│ │ │
│ ▼ scheduled re-scan │
│ Drift detection ──► live ≠ pinned ? ──► DriftEvent (rug-pull) │
│ │ │
│ ▼ │
│ Policy engine (auto-block / hold) ──► hash-chained WORM audit log │
└─────────────────────────────────────────────────────────────────────────┘
│ only approved + pinned
┌── Distribution (door out)─▼─────────────────────────────────────────────┐
│ One-click install · curl|sh, hash-verified · vouched MCP config │
└─────────────────────────────────────────────────────────────────────────┘
```
应用程序作为一个单一的 Spring Boot 部署单元启动,具有清晰的内部模块边界(parser、scanner、registry、audit、notify、policy、tenancy)。PostgreSQL 用于保存 registry、锁定的版本、审计日志、抑制规则和策略。
## 快速开始(本地)
你只需要一个容器运行时——**Docker**(带有 compose 插件)或 **Podman**(rootless),以及在开发环境下用于控制台的 Node 20。
```
# 1) Backend + Postgres(在 containers 内构建 — 无需本地 JDK)
docker compose up --build -d # or: podman compose up --build -d
# health: curl -s localhost:8080/actuator/health → {"status":"UP"}
# 2) Console(dev server,hot reload)
cd console
npm install
API_PROXY_TARGET=http://localhost:8080 npm run dev
# → http://localhost:3000 (dev 登录:admin@vouchq.local / admin)
```
API 文档(OpenAPI / Swagger UI)由后端在 `/swagger-ui` 路径下提供。
如果您本地有 JDK 21,您可以直接使用 Gradle wrapper:
```
./gradlew :parser:test :scanner:test # OSS unit tests (no container needed)
./gradlew build # full build (app tests use Testcontainers → needs a container runtime)
```
### 生产环境(自托管,Docker Compose)
一个全新的实例会发起**零次出站调用**——每一项集成都需要主动开启。经过安全加固的 `compose.prod.yaml` 会作为一个整体启动整个技术栈——**Postgres + 后端 + 控制台**:
```
cp .env.prod.example .env && chmod 600 .env # fill in the required secrets
docker compose -f compose.prod.yaml --env-file .env up -d --build
# (podman compose -f compose.prod.yaml --env-file .env up -d --build 的运行效果完全相同)
```
**控制台**是位于 `127.0.0.1:3000` 的前端入口(它会在内部将 `/api` 代理给后端)——请将您负责 TLS 终止的反向代理指向它。Postgres 永远不会对外发布;后端仅绑定本地回环地址以供运维使用。
经过安全加固的 `compose.prod.yaml` 涵盖了密钥生成(通过 `.env.prod.example`)、首次启动的 admin 账户以及安全默认设置;用于替代部署方案的 systemd(rootless Podman)单元位于 [`deploy/quadlet/`](deploy/quadlet/) 中。
## 技术栈
Java 21 · Spring Boot 3 · PostgreSQL · Flyway · Gradle(多模块)· 控制台:Next.js (App Router) + TypeScript + Tailwind。
**对自托管友好**(规范 §7):仅使用标准依赖项;所有出站流量(遥测、通知)都是可选的,且**默认关闭**。构建过程是多阶段的,运行时镜像以非 root 用户身份只读运行。GitHub Actions 会在每次推送/PR 时构建每个模块,并运行完整的测试套件(包括 Testcontainers 集成测试)、控制台构建以及容器镜像的冒烟测试构建。
## 文档
- **[威胁模型](docs/threat-model.md)** —— Vouchq 可防御的内容,及其明确不防御的内容
- **[Vouchq 如何比较](docs/comparison.md)** —— 对比 MCP registries、gateways 和 scanners
- **[扫描器规则](docs/scanner-rules.md)** —— 完整的规则目录 + 如何添加规则(适合作为首个贡献)
- 部署:参见上文的 **生产环境(自托管,Docker Compose)** + `.env.prod.example`
- API:在运行后端的 `/swagger-ui` 路径查看 OpenAPI / Swagger UI
- 路线图:Linear 项目 **Vouchq**
## 社区与贡献
欢迎在整个技术栈层面做出贡献——包括新的扫描器规则、针对更多 Skill / MCP 形态的解析器覆盖、测试夹具以及控制面的改进。欢迎在 **[ma3s1r0/Vouchq](https://github.com/ma3s1r0/Vouchq)** 上提 issue 或 PR。贡献内容将在 **AGPL-3.0-or-later** 协议下授权;可能会要求签署一份轻量级的 CLA/DCO,以便该项目能够继续提供商业许可——详见 [`LICENSING.md`](LICENSING.md)。
## 许可协议
**在 [AGPL-3.0-or-later](LICENSE) 下完全开源**——包括整个技术栈以及附带的库。AGPL 的网络条款确保即使作为服务运行,每一部分也保持开放。对于无法接受 AGPL 的组织,我们提供单独的商业许可。完整的原则声明与条款:**[`LICENSING.md`](LICENSING.md)**。
标签:AI安全, Chat Copilot, MCP工具, Spring Boot, StruQ, 后台面板检测, 哈希锁定, 域名枚举, 完整性校验, 文档安全, 请求拦截