内容
<div align="center">
<img src="logo.png" alt="Doberman logo" width="200">
# Doberman
**自适应授权与AI编码代理运行时防护**
[](https://github.com/fu351/Doberman-Core/actions/workflows/ci.yml)
[](./LICENSE)
[](https://www.python.org/downloads/)
[](#roadmap)
[](https://discord.gg/Sfy5XGNqty)
你的AI编码代理可能会执行`rm -rf`命令,泄露你的API密钥,或者被提示注入从而导致数据外泄 —— **自主运行,无撤销机会**。Doberman是执行路径上的守卫犬,能够在危险的调用执行前阻止它。
</div>
<p align="center">
<img src="docs/assets/dash-demo.gif" alt="The doberman demo attack reel against the live dashboard: a secret exfiltration, a destructive rm -rf, a protected-branch force push, a smuggled-token egress and a .env read are blocked in the live feed, then a human denies a high-risk SSH-trust-file write from the pending-approvals queue" width="820">
<br>
<em><code>doberman demo</code> against the live dashboard (<code>doberman dash</code>): five attacks blocked as they happen, then a human denies a high-risk approval.</em>
</p>
> 如果不在执行路径上,那么它就是建议性的,而不是保护性的。
Doberman位于**代理和其工具之间** —— 一个透明的**MCP代理**或**主机钩子** —— 并将每个操作转换为明确、可审计的决策。每个工具调用都会得到一个明确的结果,该结果会在调用执行前决定:
| 结果 | 会发生什么 |
|---|---|
| **通过** | 例行工作 —— 直接通过,无阻碍。 |
| **授权** | 敏感操作 —— 暂停等待一次性审批。 |
| **阻止** | 危险操作 —— 直接阻止,永不执行。 |
```
AI代理 ──▶ Doberman ──▶ 真实工具(文件、shell、MCP服务器、API)
└─ 标准化 → 风险引擎 → 通过 / 授权 / 阻止
```
适用于 **Claude Code, Cursor, Codex, Copilot,以及任何MCP兼容的代理**。开源,本地优先,并受两个规则约束:它 **关闭失败**(不确定性拒绝)和 **仅提升**(可以自动收紧,但绝不无声放松)。
<div align="center">
### [通过两个命令获取保护](#快速开始) · [加入Discord讨论组](https://discord.gg/Sfy5XGNqty)
</div>
---
## 目录
- [为什么选择Doberman?](#为什么选择Doberman) —— 它做什么,以及两个保证
- [快速开始](#快速开始) —— 通过两个命令安装并保护代理
- [验证端到端](#验证端到端) —— 在真实的MCP服务器上验证
- [转换门](#转换门) —— 可选的预推理检查点
- [基准测试](#基准测试) —— 攻击阻止率(ASR)与误报率(FPR)
- [编写自定义防护规则](#编写自定义防护规则插件) —— 注册自己的规则作为插件
- [调整风险容忍度](#调整风险容忍度) —— 严格模式 + 执行控制
- [谁适合使用?](#谁适合使用)
- [路线图](#路线图)
- [贡献](#贡献) · [许可证](#许可证)
---
## 为什么选择Doberman?
提示注入、工具中毒、数据外泄和失控代理是AI代理的安全问题。大部分“AI防护”检查提示并提供建议。Doberman不同,它位于 **工具执行路径上**,因此被阻止的操作 **永远不会执行**。
这三个结果不是模型可以谈判的建议 —— 每个结果都在调用执行前的关键节点强制执行。无论模型自己的防护如何,操作都必须经过Doberman的检查。
**两个不可妥协的特性:**
- **关闭失败** —— 任何错误、不确定性或未处理的情况都会拒绝操作。没有路径可以绕过决策引擎。
- **仅提升学习** —— 防护和自适应学习可以自动 **收紧**,绝不会无声放松。每个永久性策略削弱都需要明确的、基于占有因素的审计批准(如果已注册TOTP,否则为本地Doberman密码)。
---
## 快速开始
Doberman保护任何 **MCP兼容** 的编码代理:选择你的代理,运行一个命令,每个工具调用都会在执行前审查。完整的演练 - 每个选项、标志、仪表板和健康检查 - 都在 **[设置指南](docs/SETUP.md)** 中。
```bash
pip install doberman-core
```
| 你的代理 | Doberman如何连接 | 开始使用 |
|---|---|---|
| **Claude Code** | 钩子 - 控制每个内置和MCP工具调用 *(推荐)* | `doberman setup` -> [指南](docs/SETUP.md#claude-code-hooks) |
| **Claude Desktop / Cursor / Codex** | MCP代理 - 包装你的工具服务器 | `doberman serve -- <your-server>` -> [指南](docs/SETUP.md#mcp-proxy) |
| **OpenClaw** | 原生插件适配器 | [指南](docs/SETUP.md#openclaw) - [适配器](adapters/openclaw/README.md) |
| **任何MCP兼容的代理** | MCP代理 | [指南](docs/SETUP.md#mcp-proxy) |
**最快捷的方式 - Claude Code:**
```bash
doberman setup # 选择严格模式,调整防护规则,连接钩子
```
Doberman现在审查你的代理做的每个工具调用。使用 `doberman doctor`确认,或使用 `doberman demo`查看实际的结果。其他所有内容 - MCP代理连接、仪表板、TUI、扫描和2FA - 都在 **[设置指南](docs/SETUP.md)** 中。
---
## 验证端到端
两种方法可以查看Doberman在 **真实** MCP服务器上运行:
**交互式演示 - MCP Inspector + 真实文件系统服务器:**
```bash
npx -y @modelcontextprotocol/inspector doberman serve -- npx -y @modelcontextprotocol/server-filesystem ~/my-project
```
打开Inspector UI,通过Doberman调用工具:例行读取和写入操作直接通过到真实文件系统服务器;破坏性调用以策略错误返回,永不执行。
**端到端测试 - 在开发检查点:**
```bash
pytest tests/integration/test_serve_end_to_end.py -q
```
这会启动 `doberman serve`作为一个真实的子进程,前面连接一个真实的stdio工具服务器([`tests/fixtures/stdio_tool_server.py`](tests/fixtures/stdio_tool_server.py)),使用一个真实的MCP客户端模拟代理,并断言可部署的链条覆盖实际的stdio:
1. 下游的工具通过代理重新暴露,
2. 通过结果到达工具(下游的调用日志记录它),
3. 阻止结果(`rm -rf /`)永远不会到达 - 调用日志保持为空。
这个最后的断言是项目依赖的 **检查点属性**。
> **测试夹具说明:** 集成套件的其他部分故意使用 **进程内** 的假下游([`tests/fixtures/fake_tool_server.py`](tests/fixtures/fake_tool_server.py))记录执行的每个调用 - 记录是测试证明阻止的操作是否到达 **什么都没有**。它是测试夹具,而不是运行时。`doberman serve`总是启动并与你给出的真实服务器通信。
---
## 转换门
**第二个调用点** 用于相同的决策引擎 - 在用户 **预推理钩子** 处咨询,因此在用户的 **回合** (提示 + 附加/粘贴/工具获取的内容)上判断一个明显的 **回合** 在花费单个推理令牌 **之前** 。转换门是一个 **效率/早期警告** 层,具有刻意狭窄的保证 - **没有Tier-0签名回合到达模型** 。 **上面的动作门仍然是安全保证** :攻击者如果绕过转换门,仍然会遇到它。
- **一个引擎,两个调用点。** `decide_turn` 重用仅限提升的 `combine`,决策审计模型和分层认证挑战 - **零个新结果权限** 。它不需要对动作路径进行任何更改;`turngate/` 是一个新的适配器(兄弟代理),引擎保持纯粹(将分层防护注入)。回合结果附加到相同的编辑 `decisions` 日志,标记为 `action_type='turn'` 。
- **第0层 - 确定性签名(唯一硬阻止,小而设计)。** `instruction_nullification`,`authority_override` (冒充/模式切换/“打印系统提示”),`secret_export` 和 `encoded_payload` 。精度核心是 **问题与提及鉴别器** + **来源规则** :来自 *不受信任* (粘贴/工具获取)内容的匹配无条件阻止; *键入 + 发出* 的匹配阻止; *键入 + 提及* (引用/元讨论)的匹配提升到AUTH,因此研究人员讨论攻击不会被硬阻止;模糊 → 发出;代码围栏永远豁免。
- **第1层 - 启发式召回(仅限AUTH,不能阻止)。** 嵌入式代理定向指令在 *粘贴* 文本(不是简单的命令式语气,因此教程不会触发),角色覆盖,亚阈值混淆和紧迫性+保密性框架 - 错误的积极性仅需一次点击,而不是拒绝提示。
- **风格共现门控.** 每个实体一个 **提示风格基线** (仅粗略标量桶 - 长度,单词形状,标点/大小写/数字密度;绝不会是文本)为每个回合的风格评分,作为经验累积分布函数的p值,相同的校准理念用于主观基线 - **绝不会单独根据风格** (人们的输入方式不同,疲劳/移动/粘贴;设备或语言切换是漂移,而不是攻击)。风格异常单独 **标记,不门控** ,并在提示基线成熟之前保持惰性(与基线的其他成熟度规则相同);第0层从第一个回合开始激活。已知限制:共享帐户会混合打字者,降低风格信号趋向噪声 - 共现将成本限制在额外的一次点击。
- **标记和传递:回合信号馈送动作阶段(仅限提升)。** 每个 **释放** 的回合发布其风格测量值和启发式标志作为每个实体的 `TurnContext` 。动作阶段通过两种方式消耗它 - 主观惊讶项接受 **有界,非负** 贡献(标记的回合使其后续动作评分更严格;干净的回合贡献完全为零),动作追踪到 **标记的粘贴段** 继承 `provenance: untrusted_data` ,使其达到致命三重奏的底线。按构造仅限提升;阻止的回合发布 **零** 。
- **重复后阻止逃生口令。** 刚刚被阻止的近似重传回合被视为故意人为意图,并通过 **缩放为阻止** 的证明(第0层签名 → `two_factor` ;重放循环无法产生TOTP),**原始原因重述** 。审批是一次性的;第三次尝试在TTL内锁定。
- **优先认证和温和缺失。** `BLOCK` 保留用于明显的情况;所有可疑情况都要求人类。任何内部错误 **对人类失败** (认证),永远不会无声通过。没有主机预推理钩子(纯MCP代理部署)或 `DOBERMAN_TURN_GATE=off` ,门控简单缺失,动作门控承载所有。
---
## 基准测试
套件无关的测试框架将Doberman作为 **标记动作过滤器** 进行评分,并报告 **ASR** (攻击绕过率)和 **FPR** (良性过度阻塞/摩擦)。它在每个标记的工具调用上运行真正的决策引擎 - Doberman是过滤器,而不是代理 - 因此门控路径是确定性和离线的。
```bash
python -m tests.benchmarks.run --suite synthetic --profile both # 内置与插件
python -m tests.benchmarks.run --suite synthetic --profile before_after # 没有防护与使用Doberman
```
它报告两种插件配置文件 - `builtins_only` 和 `with_plugins` (内置项加上已安装的入口点插件)及其提升。 `before_after` 配置文件添加了一个 **无防护基线** (未调解的工具路径,每个攻击都会执行),因此您可以直接读取引擎的效果作为 `{before, after, delta}` - 它阻止了多少原本会执行的攻击,以及它增加了多少良性摩擦。 确定性综合测试套件在CI中门控;映射外部任务套件( **AgentDojo** ,AgentDyn,AgentSentry,…)到核心类型的小适配器 - 请参见 [`tests/benchmarks/README.md`](tests/benchmarks/README.md)。
> 报告仅包含计数、结果和原因代码 - 绝不包含有效载荷文本。 ASR与更严格的 `asr_strict` 一起报告(仅硬 `BLOCK` 计为缓解):诚实的衡量标准,而不是单一的标题数字。
---
## 编写自定义防护规则(插件)
第三方规则通过 **`doberman.rules`** 入口点组注册。核心永远不会按名称导入您的包 - 安装它,`discover_rules()` /目标防护规则自动拾取。
一个五分钟的工作示例位于 [`examples/plugin-guardrail/`](examples/plugin-guardrail/) (从git checkout):
```bash
pip install -e ".[dev]"
pip install -e examples/plugin-guardrail
pytest examples/plugin-guardrail/tests -q
pip uninstall -y doberman-example-plugin-guardrail # 可选:恢复核心发现
```
教程规则将写入 `SECRETS_TODO.md` 的写入提升到AUTH,保持仅限提升,绝不将路径或有效载荷放入其解释中。复制软件包时,您需要一个真正的自定义规则。
> 在安装示例时,核心的“未注册插件”检查将看到它 - 这是预期的。 如果您不想干净的环境,请在运行完整的核心套件之前卸载它。
---
## 调整风险容忍度
在 `.doberman/policies.yaml` 或通过 `doberman mode <mode>` 中设置模式。 每次模式更改都记录在仅追加的策略更改日志中(使用 `doberman policy-history` 视图)。 降低严格性(偏执 → 严格 → 平衡 → 轻松)是 **削弱** ,需要确认和占有因素: **如果已注册TOTP,否则为本地Doberman密码** 。如果两者都不存在,则降低失败关闭;仅确认永远不够。
| 模式 | 最适合 | 批量删除阈值 | 未知目的地提升 | 行为异常提升 | 致命三重奏外泄 |
|---|---|---|---|---|---|
| **轻松** | 探索/受信任环境 | 100 文件 | 否 | 否 | 认证 |
| **平衡** *(默认)* | 日常编码代理 | 25 文件 | 否 | 是 | 认证 |
| **严格** | 生产仓库,共享代码库 | 10 文件 | 是 | 是 | **阻止** |
| **偏执** | 高度自主或安全关键代理 | 3 文件 | 是 | 是 | **阻止** |
> 硬阻止(秘密外泄,破坏性命令,角色边界违规,带走令牌通道外泄)在 **每种模式下都是相同的** 。 模式拨盘仅影响在哪里需要对模糊或高风险操作进行逐步身份验证。
> **未知网络目的地** 仅在严格/偏执模式下提升到身份验证。轻松和平衡模式将纯未知主机(例如,获取文档站点或API)视为允许 - 该身份验证在几乎每个Web获取中触发,并且是良性提示的顶级来源。 这仅放松 **目的地单独** 的信号:离开到 **任何** 主机的秘密仍然是硬阻止(秘密规则 + 仅限提升组合,每个模式),而更尖锐的目的地气味(嵌入URL的凭证,原始IP地址,不可解析的主机)仍然在每种模式下提升。 **超出范围的角色目标** 同样在平衡/严格/偏执模式下提升,但在轻松模式下放松; **阻止** 的目标在每种模式下都是硬阻止。
> 一种升级是模式门控: **致命三重奏** - **敏感数据** 和 **不受信任的内容来源** 和 **外部目的地** - 在轻松/平衡模式下提升到身份验证,在严格/偏执模式下是 **硬阻止** 。这些高安全模式拒绝此严重外泄模式直接拒绝,而不是留下它进行确认提示,可能会因警报疲劳而被滥用。
### 执行/监控/关闭 — 执行控制
与严格模式正交的是一个**执行控制**(`enforce`(默认)/ `monitor` / `off`),它决定了 Doberman 是否根据判决采取行动或只是观察:
- **`enforce`** — 正常行为:身份验证提示,阻止拒绝。
- **`monitor`** — 一个刻意的**观察模式**。评估和记录**自主**层(行为异常,软步升级) — `doberman log` / `doberman tui` 显示将会发生什么 — 但它从不阻止或提示。使用它在存储库中尝试 Doberman 而没有摩擦,或在启用之前进行调整。
- **`off`** — 不评估自主层。
使用 **`doberman enforcement <enforce|monitor|off>`** 设置(无参数打印当前状态)。降低控制级别时需要确认 — 加上最强的**已注册**占有因素(如果注册了 2FA,则为 TOTP 代码,否则为本地 Doberman 密码)— 并记录在账本中(使用 `doberman policy-history` 查看);如果没有注册任何因素,则更改现在**失败关闭**(没有仅确认的回退 — 首先运行 `doberman password set`,然后重试)。将其恢复**向上**时会自动重新启用,没有任何限制。
**在每种状态下,目标底线都保持活跃。** 秘密外流,多步骤/确认外流,破坏性命令,受保护路径写入,角色/策略阻止以及致命三要素始终阻止 — `monitor`/`off` 只能软化**自主**判决,从不采取灾难性行动。软化控制级别需要确认和占有因素(如果注册,则为 TOTP,否则为本地密码 — 如果两者都没有注册,则失败关闭),并且在每次调用时,磁盘上的值都会经过**账本验证**,因此如果没有匹配的批准更改,手动编辑的 `enforcement: off` 在 `policies.yaml` 中被捕获并恢复到 `enforce`(失败关闭)。
### 主观偏好权重 — `doberman prefs`
自适应层的四个 SL5 "关怀" 权重(`confidentiality`,`reversibility`,`interruption_tolerance`,`blast_radius`,每个在 `[0, 1]`)调整了**自主**行为信号的启用程度 — 目标硬阻止底线从未移动。使用 `doberman prefs` 显示活动向量,设置一个权重使用 `doberman prefs <dimension> <value>`。与 `mode` 相同的永久降低规则适用:**降低**权重需要 TOTP(如果注册),否则需要本地 Doberman 密码;如果没有注册任何因素,则失败关闭,并且仅确认永远不够。**提高**权重是一种加强,始终立即应用。每个尝试,无论批准与否,都记录在仅追加的账本中。
---
## 适用人群
- **运行 AI 编码代理的开发人员**,他们希望拥有没有 `rm -rf` 轮盘赌的自主代理。
- **安全工程师**,他们评估 AI 代理安全,MCP 安全,LLM 工具使用沙盒和零信任架构,以适应 AI 代理。
- **部署代理群的平台团队**,他们需要策略执行,审计日志和人为干预审批,以阻止破坏性操作。
---
## 路线图 <a name="roadmap"></a>
计划和进行中的工作现在位于 GitHub 上 — **[Doberman 路线图看板](https://github.com/users/fu351/projects/5)**(当前关注点:主机托管,成本可观察性和企业平台)。对于已经发布的全部内容,请参阅 **[更新日志](CHANGELOG.md)**。
### 已知限制
Doberman 是**纵深防御,不是万无一失的** — 没有单一规则是保证。有一个具体的,已知的漏洞:
- **整个脚本同形混淆字符。** 确定性检查捕获**内部**混合脚本的同形混淆字符(例如 `раypal`,它混合了西里尔字母和拉丁字母)。但是,一个**完全**用一个非拉丁字母脚本渲染的令牌,模仿一个拉丁语单词(例如,一个完全西里尔字母的 `paypal` 模仿品)是 NFKC 稳定的,并且**不**被核心确定性检查捕获。目前计划通过困惑度/混淆字符检测器来解决这个问题。请将上面的 `OOD/homoglyph token signals` 项视为防御深度,而不是稳健性保证。
- **裸高熵十六进制。** 为了避免将 git SHA,内容/AST 摘要和锁文件哈希标记为秘密 — 一个嘈杂的假阳性,也会破坏多步骤污染账本 — 通用高熵启发式忽略**完全**哈希形十六进制(≥ 40 个字符)。因此,一个没有任何周围凭证名称的裸十六进制秘密不会被此启发式单独升级;它仍然会被捕获,当它带有凭证密钥名称(例如 `API_KEY=…`),匹配已知的凭证形状,或以后被读取与发送指纹匹配时。防御深度,而不是保证。
- **裸令牌固定/模式文本抑制是 WEAK-path 独有的,并且在残差上标记门控。** 一个裸(非赋值)令牌,是正则表达式模式源文本被引用(例如 `sk-ant-[A-Za-z0-9_-]{20,}`)或一个明显的书面固定装置,不会被高熵启发式单独升级(#73)。因为一个固定装置标记(`EXAMPLE`/`SAMPLE`/`FAKE`/`DUMMY`)和有序 `0-9`/`a-z` 填充器是攻击者可控的 — 而对于一个**无形**的秘密,高熵启发式是唯一的信号 — 所以一个标记本身**不**被信任:只有当标记被剥离和升序运行后,残差太短/低熵时,令牌才被抑制。一个带有 `EXAMPLE` 的真实密钥具有高熵残差并且仍然触发,而一个变量仅使用标记命名从不抑制其值(检查在 `=` 分割后在 RHS 上运行)。抑制也从不影响 STRONG 凭证形状路径,它仍然可以驱动 `secret_exfiltration`。正则表达式源(`[]{}\`)被无条件抑制 — 标记器字符集无法在真实令牌中生成这些字符。防御深度,而不是保证:一个完整的,类似真实的示例密钥在散文中引用,没有标记仍然无法与真实的密钥区分,并且升级。
- **静态出口分类,而不是运行时出口代理。** Doberman 现在从**shell / package / git 命令**中读取外部目的地 — 不仅仅是 `network_request` 调用 — 因此一个秘密通过 `curl <host>` 传输是一个硬**阻止**,并且**任何**此类命令出口(即使到一个看似受信任的主机,或它无法解析为单个路由的主机)升级到**身份验证**。这是**仅提升**:它从不创建新的无声允许,并且模糊**朝向**人类失败。但是,它是对命令字符串的静态解析 — 它可以标记“这看起来像出口”,但无法证明被分类的主机是进程实际打开的套接字。重定向文件,`--resolve`/`--connect-to`,`HTTP(S)_PROXY`/`ALL_PROXY` 覆盖,DNS 重新绑定,在运行时构建的 URL,在已经配置的源上进行 `git push`,软件包生命周期脚本,被滥用为通道的受信任租户,或者来自派生子进程的出口都可以仍然绕过静态分类器。真正的遏制需要一个运行时出口代理(计划中)。防御深度,而不是保证。
- **通过标志获取的透明包装出口升级到 AUTH — 静态分类仍然可绕过。** 当出口命令通过一个获取其自身标志的包装调用时(例如 `sudo -u www-data curl …`,`nice -n 10 curl …`,`ionice -c 2 wget …`),包装的选项转换 argv,因此选项被误读为命令。Doberman 检测到隐藏的命令,并在 shlex 规范化的命令令牌命名已知出口工具时,将其升级到**身份验证**,包括引号分割(`cu''rl`)或路径限定(`/usr/bin/curl`)动词。这是**仅提升**(它从不创建新的无声允许),但仍然存在两个诚实的限制:(1)静态解析无法恢复**包装**命令的主机,因此一个包装的秘密出口解析为**AUTH,而不是硬阻止**其未包装形式获得(秘密出口底线需要它看不到的主机);和(2)一个动词被混淆到标记规范之外 — 一个嵌套 shell(`sh -c '…'`),命令替换(`$(…)`),或在运行时组装的名称 — 仍然可以避免静态分类器,而一个仅用作参数的裸出口名称(`grep curl x`)则相反升级到 AUTH(一个刻意的失败关闭成本)。这里的强大遏制需要运行时出口代理(计划中)。防御深度,而不是保证。
---
## 贡献
首先参阅 [CONTRIBUTING.md](CONTRIBUTING.md),了解本地设置,CI 检查,项目不变性和 PR 工作流程。
**来打个招呼。** 问题,想法,共享规则包或在野外捕获的攻击?
[**加入 Discord 群组 →**](https://discord.gg/Sfy5XGNqty) — 这里是路线图形成的地方。
**发现漏洞或绕过防护措施?** 请私下报告 — 参见
[SECURITY.md](SECURITY.md)。不要为安全报告打开公共问题或 Discord帖子。
---
## 许可证
Apache-2.0。核心是真正独立的 — 从未有过专有依赖(CI 强制执行)。
---
<sub>AI 代理安全 · MCP 安全 · MCP 代理 · MCP 防火墙 · AI 防护栏 · 代理 AI 安全 · 提示注入防御 · 工具中毒防御 · LLM 工具使用授权 · 人在环中的 AI · AI 代理沙盒 · 运行时 AI 安全 · AI 代理的零信任 · Claude Code 安全 · 自主代理治理 · 数据流出预防 · 自适应异常检测 · 开源 AI 安全</sub>
连接信息
猜你喜欢
暂无推荐服务器