@aimarket/warden 0.20.0 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +113 -0
- package/README-es.md +27 -11
- package/README-fr.md +27 -11
- package/README-ru.md +27 -11
- package/README-zh.md +27 -11
- package/README.md +27 -11
- package/dist/annotation-review.d.ts +10 -0
- package/dist/annotation-review.d.ts.map +1 -0
- package/dist/annotation-review.js +36 -0
- package/dist/annotation-review.js.map +1 -0
- package/dist/atomic-screen.d.ts +61 -0
- package/dist/atomic-screen.d.ts.map +1 -0
- package/dist/atomic-screen.js +165 -0
- package/dist/atomic-screen.js.map +1 -0
- package/dist/flow-guard-answer.d.ts +29 -0
- package/dist/flow-guard-answer.d.ts.map +1 -0
- package/dist/flow-guard-answer.js +201 -0
- package/dist/flow-guard-answer.js.map +1 -0
- package/dist/flow-guard-classify.d.ts +14 -0
- package/dist/flow-guard-classify.d.ts.map +1 -0
- package/dist/flow-guard-classify.js +224 -0
- package/dist/flow-guard-classify.js.map +1 -0
- package/dist/flow-guard-decode.d.ts +17 -0
- package/dist/flow-guard-decode.d.ts.map +1 -0
- package/dist/flow-guard-decode.js +149 -0
- package/dist/flow-guard-decode.js.map +1 -0
- package/dist/flow-guard-destinations.d.ts +23 -0
- package/dist/flow-guard-destinations.d.ts.map +1 -0
- package/dist/flow-guard-destinations.js +158 -0
- package/dist/flow-guard-destinations.js.map +1 -0
- package/dist/flow-guard-fingerprints.d.ts +27 -0
- package/dist/flow-guard-fingerprints.d.ts.map +1 -0
- package/dist/flow-guard-fingerprints.js +164 -0
- package/dist/flow-guard-fingerprints.js.map +1 -0
- package/dist/flow-guard-fragments.d.ts +17 -0
- package/dist/flow-guard-fragments.d.ts.map +1 -0
- package/dist/flow-guard-fragments.js +122 -0
- package/dist/flow-guard-fragments.js.map +1 -0
- package/dist/flow-guard-instructions.d.ts +12 -0
- package/dist/flow-guard-instructions.d.ts.map +1 -0
- package/dist/flow-guard-instructions.js +36 -0
- package/dist/flow-guard-instructions.js.map +1 -0
- package/dist/flow-guard-labels.d.ts +10 -0
- package/dist/flow-guard-labels.d.ts.map +1 -0
- package/dist/flow-guard-labels.js +55 -0
- package/dist/flow-guard-labels.js.map +1 -0
- package/dist/flow-guard-leak.d.ts +29 -0
- package/dist/flow-guard-leak.d.ts.map +1 -0
- package/dist/flow-guard-leak.js +135 -0
- package/dist/flow-guard-leak.js.map +1 -0
- package/dist/flow-guard-paths.d.ts +21 -0
- package/dist/flow-guard-paths.d.ts.map +1 -0
- package/dist/flow-guard-paths.js +72 -0
- package/dist/flow-guard-paths.js.map +1 -0
- package/dist/flow-guard-policy.d.ts +15 -0
- package/dist/flow-guard-policy.d.ts.map +1 -0
- package/dist/flow-guard-policy.js +179 -0
- package/dist/flow-guard-policy.js.map +1 -0
- package/dist/flow-guard-post.d.ts +6 -0
- package/dist/flow-guard-post.d.ts.map +1 -0
- package/dist/flow-guard-post.js +131 -0
- package/dist/flow-guard-post.js.map +1 -0
- package/dist/flow-guard-pre.d.ts +13 -0
- package/dist/flow-guard-pre.d.ts.map +1 -0
- package/dist/flow-guard-pre.js +335 -0
- package/dist/flow-guard-pre.js.map +1 -0
- package/dist/flow-guard-screen.d.ts +85 -0
- package/dist/flow-guard-screen.d.ts.map +1 -0
- package/dist/flow-guard-screen.js +558 -0
- package/dist/flow-guard-screen.js.map +1 -0
- package/dist/flow-guard-state.d.ts +12 -0
- package/dist/flow-guard-state.d.ts.map +1 -0
- package/dist/flow-guard-state.js +121 -0
- package/dist/flow-guard-state.js.map +1 -0
- package/dist/flow-guard-text.d.ts +9 -0
- package/dist/flow-guard-text.d.ts.map +1 -0
- package/dist/flow-guard-text.js +46 -0
- package/dist/flow-guard-text.js.map +1 -0
- package/dist/flow-guard-types.d.ts +154 -0
- package/dist/flow-guard-types.d.ts.map +1 -0
- package/dist/flow-guard-types.js +2 -0
- package/dist/flow-guard-types.js.map +1 -0
- package/dist/flow-guard.d.ts +20 -215
- package/dist/flow-guard.d.ts.map +1 -1
- package/dist/flow-guard.js +26 -1400
- package/dist/flow-guard.js.map +1 -1
- package/dist/mcp-client.d.ts +1 -2
- package/dist/mcp-client.d.ts.map +1 -1
- package/dist/mcp-client.js +2 -19
- package/dist/mcp-client.js.map +1 -1
- package/dist/mcp-server.js +5 -0
- package/dist/mcp-server.js.map +1 -1
- package/dist/mcp-tools.d.ts.map +1 -1
- package/dist/mcp-tools.js +46 -9
- package/dist/mcp-tools.js.map +1 -1
- package/dist/public-address.d.ts +3 -0
- package/dist/public-address.d.ts.map +1 -0
- package/dist/public-address.js +58 -0
- package/dist/public-address.js.map +1 -0
- package/dist/review-diff.d.ts +36 -0
- package/dist/review-diff.d.ts.map +1 -1
- package/dist/review-diff.js +177 -7
- package/dist/review-diff.js.map +1 -1
- package/dist/task-adapter.d.ts +73 -0
- package/dist/task-adapter.d.ts.map +1 -0
- package/dist/task-adapter.js +379 -0
- package/dist/task-adapter.js.map +1 -0
- package/dist/task-cli.d.ts +3 -0
- package/dist/task-cli.d.ts.map +1 -0
- package/dist/task-cli.js +162 -0
- package/dist/task-cli.js.map +1 -0
- package/dist/types.d.ts +9 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/wrap-cli.d.ts +5 -0
- package/dist/wrap-cli.d.ts.map +1 -1
- package/dist/wrap-cli.js +29 -2
- package/dist/wrap-cli.js.map +1 -1
- package/dist/wrap-screen.d.ts +3 -0
- package/dist/wrap-screen.d.ts.map +1 -0
- package/dist/wrap-screen.js +20 -0
- package/dist/wrap-screen.js.map +1 -0
- package/dist/wrap-state.d.ts +8 -1
- package/dist/wrap-state.d.ts.map +1 -1
- package/dist/wrap-state.js +21 -4
- package/dist/wrap-state.js.map +1 -1
- package/dist/wrap.d.ts.map +1 -1
- package/dist/wrap.js +204 -10
- package/dist/wrap.js.map +1 -1
- package/docs/flow-guard-model-comparison-2026-10-25.es.md +82 -0
- package/docs/flow-guard-model-comparison-2026-10-25.fr.md +82 -0
- package/docs/flow-guard-model-comparison-2026-10-25.md +82 -0
- package/docs/flow-guard-model-comparison-2026-10-25.ru.md +82 -0
- package/docs/flow-guard-model-comparison-2026-10-25.zh.md +82 -0
- package/docs/flow-guard.es.md +307 -12
- package/docs/flow-guard.fr.md +307 -12
- package/docs/flow-guard.md +315 -13
- package/docs/flow-guard.ru.md +314 -13
- package/docs/flow-guard.zh.md +306 -8
- package/docs/scan-limits.es.md +39 -0
- package/docs/scan-limits.fr.md +39 -0
- package/docs/scan-limits.md +39 -0
- package/docs/scan-limits.ru.md +39 -0
- package/docs/scan-limits.zh.md +39 -0
- package/docs/scan.es.md +2 -0
- package/docs/scan.fr.md +2 -0
- package/docs/scan.md +2 -0
- package/docs/scan.ru.md +2 -0
- package/docs/scan.zh.md +2 -0
- package/docs/security-hardening.es.md +1 -1
- package/docs/security-hardening.fr.md +1 -1
- package/docs/security-hardening.md +1 -1
- package/docs/security-hardening.ru.md +1 -1
- package/docs/security-hardening.zh.md +1 -1
- package/examples/atomic-screen-server.mjs +42 -0
- package/native/macos/Package.swift +9 -0
- package/native/macos/Sources/WardenDesktop/NativeSurface.swift +246 -0
- package/native/macos/Sources/WardenDesktop/StandardIO.swift +139 -0
- package/native/macos/Sources/WardenDesktopHost/Main.swift +211 -0
- package/package.json +18 -6
- package/scripts/build-macos.mjs +22 -0
package/docs/flow-guard.zh.md
CHANGED
|
@@ -2,6 +2,285 @@
|
|
|
2
2
|
|
|
3
3
|
> 🌐 [English](flow-guard.md) · [Русский](flow-guard.ru.md) · [Español](flow-guard.es.md) · [Français](flow-guard.fr.md) · **中文**
|
|
4
4
|
|
|
5
|
+
关于账单、包版本固定、launcher 比较及批准计数的含义,请参见[测量边界与版本证据](scan-limits.zh.md)。
|
|
6
|
+
|
|
7
|
+
## 首次注解审核与回答复查(本地源码,2026-10-25)
|
|
8
|
+
|
|
9
|
+
用户策略可选择 `{"annotationReview":"first-use"}`,**仅在 `wrap --flow NAME` 中**增加首次使用确认。默认 `off`;普通 wrap 或单独 hooks 不增加要求。对没有操作员标签的工具,`readOnlyHint`、`destructiveHint`、`openWorldHint` 都是未经验证的服务器声明:任意布尔值,或已知 hint 的非法类型,都可能要求审核。`readOnlyHint: true` 既不能证明无写入,也不能证明免费。操作员明确标签及与精确身份/完整 tools 快照匹配的 capability bindings 优先;目标白名单和调用参数中的注解不授予权限。
|
|
10
|
+
|
|
11
|
+
审核只保存在当前 wrap 进程内,并绑定精确启动身份和完整定义快照。接受后,代理等待旧列表完成并请求新列表,然后在转发前重新检查共享 flow 风险。定义变化、新的拒绝/ask 原因、用户拒绝或缺少表单时不执行;没有变化的正常 ask 原因仍可批准。这不是相对于其他代理的原子事务。新 wrap 重新询问。逐次敏感调用确认、凭据边界和 GUI 守卫仍独立生效。`audit` 只记录,`off` 关闭此检查。这不是计费验证,也不是完整的效果分类器。
|
|
12
|
+
|
|
13
|
+
已知额外成本:第一次 precheck 可能已消耗精确的一次性 `credentialEgress` 规则。批准后的再次检查即使面对相同 payload 也会保守拒绝,而且规则仍已消耗。该控制计为额外摩擦,不能算作正常自动通过。
|
|
14
|
+
|
|
15
|
+
Stop 不再因句中出现 “ignored” 或 “flagged” 而豁免检查:同一句仍可能重复被注入的推荐。与已记录指令片段存在规范化后精确 12 字符窗口重合时,会请求额外回答复查。**诚实的警告也会付出这一次额外处理。** 继续执行依赖 host 的 `stop_hook_active` 标记,没有独立持久化循环计数器。释义、没有匹配指令的记录选择污染和语义正确性仍未解决。来源提示/复查不等于阻止攻击。[研究](../../docs/growth/kevin-annotations-answer-review-2026-10-25.ru.md) 区分 Linux 确定性测试与模型评估;改动仅在本地,尚未发布,历史模型结果未重新计算。
|
|
16
|
+
|
|
17
|
+
2026-10-23 后续审计:工具结果中的 `image`/`audio` 二进制数据不再占用文本预算,因此排在文本之前的大幅截图不会再遮蔽元素标签、包含凭据文件名的窗口标题或文本块中的 JSON。指针和键盘操作(包括 `computer` 操作)返回的屏幕也会更新视图。普通执行确认保留上一视图;仅返回图像的操作会清空视图。此例外不适用于传出的参数,伪装成二进制数据的秘密仍会接受检查。回归测试通过 hooks 和真实 stdio 代理复现了这两种绕过。本地源码现在也会对不透明的 GUI 操作要求确认,详见下文。
|
|
18
|
+
|
|
19
|
+
这些屏幕控制修复随 npm `0.21.0` 发布。npm `0.20.0` 不包含它们。
|
|
20
|
+
|
|
21
|
+
## 凭据边界与编码片段(本地源码,2026-10-23)
|
|
22
|
+
|
|
23
|
+
记录凭据读取和外部文本之后,**每个受支持的传出/MCP 调用都要求执行前 `ask`**(`deny` 拒绝),不因片段长度、编码、用户点名的目标或 MCP 只读标签而豁免。普通项目文件写入也需审核;凭据文件写入保留原有例外。`credentialRead` 跨轮次、跨来源历史轮换持续存在。这样阻止一至四字符和未知编码数据自动发出,依靠的是边界审核,不是声称能解码所有信息。
|
|
24
|
+
|
|
25
|
+
已识别秘密仍拒绝;歧义片段使用 `secret_fragment`。其他边界审核使用 `credential_egress`,不把正常文本误称为秘密。GUI 默认仍严格,连复制快捷键的 GUI 例外也不能豁免此边界。`audit` 只记录,`off` 关闭保护;客户端必须遵守决定。
|
|
26
|
+
|
|
27
|
+
**减少不必要的审核:** 操作员可在受保护的用户级 `flow-policy.json` 中配置独立检查过的精确公开请求。`dist/flow-guard.js` 中的 `publicRequestDigest(tool, args)` 绑定完整工具名和全部参数,包括目标。对象键排序,数组顺序有意义。每条规则每会话只授权一次,跨代理原子预留,执行失败也消耗。参数改变、重试、额外 RPC 元数据或非法参数不适用。不能豁免已识别秘密、私有文本、个人数据、弱片段匹配、不完整扫描、存储饱和、GUI 控制、shell、破坏性动作或受保护配置。规则授权的是这些精确数据,不是证明其公开:批准编码请求前应自行检查解码内容。不会自动安装任何规则。
|
|
28
|
+
|
|
29
|
+
以下规则仅适用于 `mcp__mail__send_email`,参数为 `{"to":"bob@corp.com","subject":"status","body":"The public release is ready."}`:
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
{"credentialEgress":{"allow":[{"tool":"mcp__mail__send_email","requestSha256":"62e02f4cb9c21a472999fac9316b66fc8fefe3fcafd2b2860c32c5409dae4a65"}]}}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
启用流保护时转发的是已检查的 JSON 对象,删除被忽略的重复字段,避免隐藏值借用精确授权传出。
|
|
36
|
+
|
|
37
|
+
检查完整请求后,在本地用 `publicRequestDigest` 生成摘要。上限:32 条规则/已消费授权、1,024 个 JSON 节点、深度 32、序列化请求 16,384 个 UTF-16 单元、序列化工作累计 65,536 单元。非法配置不授予权限。日志为 `credential_public_request` / `policy_allowed`,批准结果 unknown,不声称有人接受了表单。
|
|
38
|
+
|
|
39
|
+
片段元数据仍为 `v2`。正常请求确认数:精确审核规则下 **12/12 → 0/12**;默认成本仍明确保留。
|
|
40
|
+
|
|
41
|
+
**解码与错误:** 有界队列组合 URL、规范 base64/base64url、UTF-8 hex、Unicode 标量/hex 转义、数字 HTML 实体及明确英文字符列表。最多四层变换、64 个候选、累计 524,288 个 UTF-16 单元。超预算返回 `payload_incomplete` 并要求审核,绝不视为干净结果或允许公开请求。不会执行非法字面量,不解压也不做语义猜测。损坏的状态/指纹不能授权。旧 v1 索引要求审核;新建会话并重读私有来源可恢复。哈希、位置、长度和有界传出尾部仍为敏感数据,未加密。
|
|
42
|
+
|
|
43
|
+
**测得的取舍:** 工作流程有 12 个正常请求和 16 个攻击。严格默认会审核全部 12 个正常请求;精确公开规则让这 12 个各自动通过一次。两种配置均自动放行 **0/16 攻击**,**0 次强制误拒绝**。独立的纯指纹测试使用 480 个虚构密钥和 758 个文件:0 次强制拒绝,2 个文件因短匹配需审核。这些测量不同,不能推断生产误报率。同一组 23 个案例仍为 **0/23 完整通过**,包括 `secret-chunks-6-filler` 和 `secret-spelled-out`;两个仅影响回答的案例得到说明/复查。真实 stdio 测试验证未批准的短/编码请求零次到达服务器、并发仅一次授权,且元数据和重试不能绕过。
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npm run build
|
|
47
|
+
npm test
|
|
48
|
+
node scripts/redteam/credential-egress.mjs /tmp/warden-egress.json
|
|
49
|
+
node scripts/redteam/flow-redteam.mjs /tmp/warden-redteam.json
|
|
50
|
+
node scripts/redteam/fragment-collisions.mjs /tmp/warden-fragments.json docs src test ../docs ../core
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**边界:** 这是已记录工具边界上的控制,不是通用信息流分析。未观察来源、未知/重命名集成、不调用工具的回答、时间/隐蔽信道、服务器隐藏行为、明确批准的披露和绕过决定的客户端不在保证范围内。没有检查过的规则时,正常操作也会有意增加确认。生产环境和 npm 未更改;本次已重跑下文的 AgentDojo oracle replay;真实模型、1.15 亿字符/HISTOR 测量仍为历史结果。
|
|
54
|
+
|
|
55
|
+
## 不透明的 GUI 操作(本地源码,2026-10-23)
|
|
56
|
+
|
|
57
|
+
默认严格 GUI 模式下,接收不可信内容后,已识别的 MCP 指针和键盘调用在执行前需要确认(`deny` 模式拒绝)。坐标点击、纯像素屏幕、在活动输入框按 Enter、非英语标签的自动放行路径通过**人工确认**关闭,而不是声称能理解所有屏幕。输入文字也需要确认:换行或自动提交的字段可能发送内容。即使没有记录到凭据读取,粘贴也需要确认;若已识别到凭据读取,则保留更具体的 `paste_after_secret` 原因。其余不透明 GUI 决策使用 `screen_action`。
|
|
58
|
+
|
|
59
|
+
本 GUI 规则只豁免已知单个按键字段中一个精确的全选或复制组合(`cmd+a`、`cmd+c`、`ctrl+a`、`ctrl+c`,包括支持的修饰键别名)。额外字段、按键序列、格式错误的数组、末尾换行和过长值都需要确认。可见秘密仍接受检查。已知通用控制器(`computer`、`screen_control`、`desktop_control`、`browser_control`)遇到未知或缺失动作会要求确认。只有单一 `action` 字段、且完整匹配已知观察操作(如 `screenshot` 或 `get_screen`)时才豁免。camelCase、点号及连字符形式的操作名称会被规范化。用户指定或策略允许的目标不会授权 GUI 操作。
|
|
60
|
+
|
|
61
|
+
每个服务器的最新元素列表(Playwright `[ref=e14]`、`[ref_14]`、编号列表及 JSON 节点)仅帮助解释。其他列表格式不再绕过确认;提供样例可改进说明,但阻止点击不依赖样例。提示只使用守卫识别出的规范英文词,不直接显示原始屏幕标签。批准前应检查实际窗口、目标、剪贴板及预期效果。在 stdio 代理中,每次操作都需要单独接受且勾选的 MCP elicitation 表单;没有表单、拒绝或取消时,操作不会到达服务器。Claude hook 向客户端返回 `ask`,由客户端的权限机制执行。
|
|
62
|
+
|
|
63
|
+
严格模式下确认次数会增加,包括普通导航和点击消息正文;尚未测量可用性或确认疲劳。`audit` 只记录不拦截,`off` 关闭检查。必须先记录不可信内容(截图默认不可信);运营者若把所有观察都标为 private,可能移除这一触发条件。规则覆盖已识别的操作名,不覆盖任意改名的工具、JavaScript 执行器或恶意工具的隐藏行为;这些边界仍需运营者策略与操作系统隔离。没有新增 OCR 或视觉指令分类器:仅位于像素中的注入仍可能在不调用受保护工具的情况下改变回答。本地 hooks 和真实 stdio 代理测试验证了发送前拒绝、逐次确认以及上述四种情况。这些本地改动尚未部署或发布到 npm。
|
|
64
|
+
|
|
65
|
+
最新快照现在从三个方面改善解释。坐标参数(`x`/`y`、`coordinate`、`coordinates` 或 `position`)可与唯一 JSON 元素的 `bounds`、`boundingBox`、`bounding_box` 或 `rect` 相交:仅接受有限数字形式的 `{x,y,width,height}` 或 `{left,top,right,bottom}`,宽高须为正数。矩形不包含右边界和下边界;`center` 仅在坐标完全相同时匹配。重叠、互相矛盾的矩形或引用、无效数字及 xywh/xyxy 约定不明确的数组不会产生推断目标。不会猜测屏幕、视口或缩放之间的坐标转换。匹配只说明上一次快照报告的几何位置,不代表已验证当前目标。
|
|
66
|
+
|
|
67
|
+
对于 Enter/Return,唯一的 `focused: true` 节点或 `focusedRef`/`focusedElementId`/`activeElementId` 可说明焦点元素。明确为单行的字段(`multiline: false`)若属于只有一个已识别提交控件的表单,会提示“Enter 可能提交”;多行字段则对 cmd/ctrl+Enter 给出此提示。表单关系须通过 `form`/`formId` 或 JSON 表单嵌套明确提供。缺失或冲突的焦点、未知 multiline 状态、不同表单及多个提交候选都不会推断提交。已识别的 accessibility/automation 标识和 `type: "submit"` 即使没有可见标签也能提供规范动作提示。小型词表解释 Senden、Envoyer、Enviar、Wyślij 等常见标签。标识、角色和翻译仍是不可信提示;原始 accessibility 字段不会复制到额外元数据中,也不会显示在确认提示里;现有元素引用和标签仍保留在会话状态中。
|
|
68
|
+
|
|
69
|
+
这些改进仅用于解释;屏幕元数据不授予操作权限。只在粘贴或输入后询问,会漏掉预填消息、付款和删除操作。仅凭快照中的几何、焦点或 accessibility-id,无法证明导航无害。新视图若只有图像,会清除这些提示;相互矛盾的重复节点不会被采用。hooks 与 stdio 测试同时检查解释及发送前拒绝。
|
|
70
|
+
|
|
71
|
+
## Gautam 回归:字符编码、NATO、Git 元数据与 CI
|
|
72
|
+
|
|
73
|
+
有界解码器增加十进制字符码和 NATO 单词拼写:至少五个有效标量码或五个明确 NATO 单元。空格、逗号、分号、竖线和换行分隔;未知单元、无效标量或含糊的大小写标记会中断序列。支持 alfa/alpha、juliett/juliet、xray/x-ray、数字单词/字面量、标点名称及 capital/uppercase/lowercase。也检查 5–4096 个整数的 JSON 数组。共享原有深度、候选数和文本预算;耗尽仍为 `payload_incomplete`。没有 eval 或任意解压。
|
|
74
|
+
|
|
75
|
+
解码本身不代表泄漏,仍需命中秘密模式或指纹。普通数字列表与 NATO 文章不会自动被禁止。最初 1–4 个字符即使不满足解码最小长度,仍受凭据边界保护。测试同时覆盖恢复出的密钥和正常文本,不把每个短巧合都称为秘密。
|
|
76
|
+
|
|
77
|
+
未标记 MCP 的 `git_push`、`push_files`、`git_commit`、创建提交及常见 camelCase/点分名称现归为外发或可发布的持久操作。提交消息之后可能被发布;`get_commit` / `list_commits` 仍为读取。操作员标签仍需正确配置,独立凭据边界也覆盖错误标记的 MCP。Shell Git 保留现有审核。没有执行真实 commit/push。
|
|
78
|
+
|
|
79
|
+
**本地门禁变更:**`npm run build && npm run test:redteam` 用 `--check` 跑完整 hook replay:原 23 项加 Gautam 五项,共 **28 项,其中 26 项工具攻击必须 ask/deny,两项仅回答攻击必须 note/recheck**。缺失/重复用例、结果不符或重新开放自动传输均以非零退出。故意损坏报告的测试证明门禁会失败。已写入 WARDEN/workspace CI、npm `prepublishOnly` 与发布前 registry workflow。仅修改本地配置,没有启动远程 CI、release 或发布。提示回答风险并不证明阻止模型的仅回答攻击。
|
|
80
|
+
|
|
81
|
+
复现:`npm run build`、`npm run test:redteam` 或 `node scripts/redteam/flow-redteam.mjs /tmp/warden-redteam.json --check`。代码:`test/flow-guard-gautam.test.ts`、`scripts/redteam/flow-gate.mjs`。
|
|
82
|
+
|
|
83
|
+
## 受限任务模式:减少确认并控制实际操作
|
|
84
|
+
|
|
85
|
+
默认仍为严格 GUI 模式。旧的 `gui.mode: "policy"` / `gui.allow` 仅为迁移保留解析,外部文本出现后不再自动放行点击、输入或导航按键。页面可伪造 origin、角色和 accessibility ID;几何、焦点和翻译只用于解释。`press_keys_then_execute` 等复合工具名不能使用 Copy 例外;额外 RPC 元数据也不能获得自动授权。
|
|
86
|
+
|
|
87
|
+
内置任务适配器(`node dist/mcp-server.js task`)自行执行限制:列出固定资源,读取经哈希固定的本地 UTF-8 快照而不运行 HTML/JS,并按 ID 执行人工审查过的 HTTP 操作。模型不能提供 URL、方法、请求头、正文、收件人、附件或文件路径。适配器没有浏览器配置、cookies、系统剪贴板、页面脚本、service workers、子进程或通用工具转发。普通 GUI 继续要求确认。这是受支持任务的结构化替代路径,不是任意浏览器/VM 的通用沙箱。
|
|
88
|
+
|
|
89
|
+
**明确配置:**将以下清单保存为 `<WARDEN_STATE_DIR>/task-manifest.json`,策略保存为用户 flow policy。替换快照路径、哈希和 endpoint;`expiresAt` 不得超过未来 24 小时。只公开刻意允许代理读取的资料。资源示例哈希对应精确字节 `The public release is ready.\n`。审查每个请求,再对实际保存的全部字节(包括空白和末尾换行)计算 `manifestSha256`。策略示例对应所显示的清单加一个末尾换行。不会自动安装权限。
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
{
|
|
93
|
+
"version": 1,
|
|
94
|
+
"taskId": "public-report",
|
|
95
|
+
"expiresAt": "2026-10-23T23:00:00.000Z",
|
|
96
|
+
"resources": [
|
|
97
|
+
{
|
|
98
|
+
"id": "report",
|
|
99
|
+
"title": "Public report",
|
|
100
|
+
"path": "/absolute/path/public-report.txt",
|
|
101
|
+
"sha256": "1403cece199725b166f0f6e59faa9d45e3d5a25db26080fecf95e818ac8d4d0d"
|
|
102
|
+
}
|
|
103
|
+
],
|
|
104
|
+
"operations": [
|
|
105
|
+
{
|
|
106
|
+
"id": "send_report",
|
|
107
|
+
"title": "Send reviewed report to Bob, no attachments",
|
|
108
|
+
"maxUses": 1,
|
|
109
|
+
"request": {
|
|
110
|
+
"method": "POST",
|
|
111
|
+
"url": "https://mail.example/api/send",
|
|
112
|
+
"headers": {
|
|
113
|
+
"content-type": "application/json",
|
|
114
|
+
"idempotency-key": "public-report-once"
|
|
115
|
+
},
|
|
116
|
+
"body": "{\"to\":\"bob@corp.com\",\"body\":\"The public release is ready.\",\"attachments\":[]}"
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
]
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"mode": "ask",
|
|
126
|
+
"taskAdapter": {
|
|
127
|
+
"mode": "capabilities",
|
|
128
|
+
"server": "warden_task",
|
|
129
|
+
"manifestSha256": "1531d08beffb7c86d6f236c3bdfa85a8fbac1c3e8734d701e79455c53d0d94b7"
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"mcpServers": {
|
|
136
|
+
"warden_task": {
|
|
137
|
+
"command": "node",
|
|
138
|
+
"args": [
|
|
139
|
+
"/absolute/path/warden/dist/mcp-server.js",
|
|
140
|
+
"task"
|
|
141
|
+
],
|
|
142
|
+
"env": {
|
|
143
|
+
"WARDEN_STATE_DIR": "/absolute/state/warden",
|
|
144
|
+
"WARDEN_FLOW_POLICY": "/absolute/state/warden/flow-policy.json"
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
```sh
|
|
152
|
+
node -e 'console.log(new Date(Date.now() + 3600000).toISOString())'
|
|
153
|
+
node --input-type=module -e 'import {createHash} from "node:crypto"; import {readFileSync} from "node:fs"; console.log(createHash("sha256").update(readFileSync(process.argv[1])).digest("hex"))' /absolute/state/warden/task-manifest.json
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
注册 MCP 服务 **`warden_task`**:命令 `node`,参数 `[/absolute/path/warden/dist/mcp-server.js, task]`,使用与 hooks 或 `wrap --flow warden_task` 相同的 `WARDEN_STATE_DIR` / `WARDEN_FLOW_POLICY`。该名称只能绑定 WARDEN 内置适配器;绑定第三方服务会把权限交给它。工具名或 `readOnlyHint` 不是身份认证。缺失、严格或无效策略拒绝网络操作;全局 `deny`、`audit`、`off` 也不授予执行权限。客户端自己的权限仍可能要求确认。
|
|
158
|
+
|
|
159
|
+
调用:`task_list {}`、`task_read {"id":"report"}`、`task_execute {"id":"send_report"}`。参数只能是固定 ID;额外字段、重复 JSON 键、数组及隐藏 RPC 元数据均拒绝。`task_adapter_delegated` 表示委托给可信执行器,不代表已执行或人工批准。运行时再次检查哈希、模式、期限和策略,以进程锁及 fsync 在发送前消耗共享预算。重启或修改清单不会重置已使用的 task ID。失败、结果不确定或发送后取消均消耗授权;发送前取消不消耗。状态损坏或遗留锁要求操作员核对实际结果,不能删状态盲目重试。
|
|
160
|
+
|
|
161
|
+
仅支持固定 HTTPS 请求;`loopback-test` 另外允许数值 localhost 的 HTTP,仅供隔离测试。拒绝重定向,不执行响应中的 cookies、链接或指令;限制响应大小与总耗时,不自动重试。`bearerEnv` 指向操作员指定的环境变量,令牌只发往固定 endpoint,不进入列表或审计。审计仅记录 ID 与结果,不记录正文或令牌;响应仍为不可信数据。
|
|
162
|
+
|
|
163
|
+
**支付与交易:**固定账单/账户、金额、币种及正文;使用 `maxUses: 1` 与供应商支持的固定 `idempotency-key`。一次发送不等于保证恰好结算一次。超时或错误后先与供应商对账,再授权新操作。集成测试仅使用 loopback 与合成密钥,没有真实支付。
|
|
164
|
+
|
|
165
|
+
**边界:**需信任 WARDEN 进程并保护 policy/state、运行时和 MCP 绑定。endpoint 的实际语义仍由服务实现,不能把 GET 自动视为安全。错误的人为授权、固定正文中明确授权的秘密、服务端行为、ID/顺序/时间隐蔽信道及其他工具/客户端绕过均不在保证范围内。没有增加 OCR 或任意实时 GUI 操作拦截。
|
|
166
|
+
|
|
167
|
+
**2026-10-23 验证:**在无网络、无模型 API 的本地 Docker 重跑 AgentDojo 0.1.35 / v1.2.2 确定性 oracle replay。intent 变体:成功的已投递动作攻击 0/579;正常任务免询问 57/97,完成 58/97,攻击下完成 608/949(历史为 613/949)。`ask` 视为拒绝;无参考答案和仅回答攻击未因此获安全认证。AgentDojo 没有 GUI/任务适配器工具,另用 stdio、多进程和 loopback 测试覆盖。历史真实模型、1.15 亿字符和 HISTOR 测量没有重跑。[汇总](../scripts/agentdojo/results/summary-2026-10-23-local.json)。
|
|
168
|
+
|
|
169
|
+
回归:`test/task-adapter.test.ts`、`test/flow-guard-gui-policy.test.ts`、`test/flow-guard-credential-boundary.test.ts`、`test/flow-guard-secret-regression.test.ts`,覆盖伪造标签/ID、策略模式、固定资源、并发/重启、重定向、精确收件人/正文,以及 raw、hex、base64、Unicode 和未知编码下最初 1–4 个密钥字符。模糊短匹配要求审核,不把每个巧合都误称为秘密。
|
|
170
|
+
|
|
171
|
+
## 原生 macOS 后端:在目标应用内运行 AppKit
|
|
172
|
+
|
|
173
|
+
**已实现:**Swift 包 [WardenDesktop](../native/macos/Package.swift)、`WardenDesktopSurface` 和 `WardenDesktopStandardIO` 在拥有窗口的原生应用内运行。`warden-desktop --demo` 打开真实 AppKit 窗口,按钮处理器仅执行本地操作。不会控制其他应用、发送全局输入或执行网络/付款操作。wrap 仍默认严格确认。此后端要求应用主动接入,不是通用桌面注入器。
|
|
174
|
+
|
|
175
|
+
在 WARDEN 目录构建运行。需要 macOS、Xcode command-line tools 以及活动的 WindowServer 会话。构建目标为 macOS 13+ 和本机 arm64/x86_64 架构;仅本地记录中的实际架构经过验证。包内提供源码,不提供预编译二进制,也不增加 npm 运行时依赖:
|
|
176
|
+
|
|
177
|
+
```sh
|
|
178
|
+
npm run build
|
|
179
|
+
npm run build:macos
|
|
180
|
+
node dist/mcp-server.js wrap --id macos-owned-app --flow native --screen-read screenshot --screen-atomic -- native/macos/.build/warden-desktop --demo
|
|
181
|
+
npm run test:macos
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
原生动作示例,引用为字符串。也可仅传 `x` 和 `y`,采用全局屏幕左上角为原点的 points,而非像素。遮挡或不明确的目标被拒绝:
|
|
185
|
+
|
|
186
|
+
```json
|
|
187
|
+
{"name":"click","arguments":{"index":"3"}}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
**原子边界:**prepare 保留准确的 `NSButton`、明确的 `NSObject` target、selector 和通过 `method_getImplementation` 获取并检查 ABI 的实现。MainActor commit 比较修订、实时角色/ID/边框/标签、对象身份、窗口/焦点/模态状态、整个父视图链的透明度以及 hit-test。完全透明的控件或窗口、被模态状态阻止的窗口和待显示 sheet(包括过渡期逻辑 `sheetParent` 关系)均被拒绝。hit-test 后重新读取属性,检查两个时钟,最后在所有注入 callback 返回后再次比较修订。通过 `NativeAction` 在同一主循环轮次直接调用固定 IMP。刻意绕过 `NSApp.sendAction`,因为其重写可能排队、改向,或未调用获批方法却返回成功。不使用 `AXPress`、`CGEvent`、带动画的 `performClick`、first-responder 查找或排队坐标输入。仅支持已注册、可见、启用且签名为 `void action(id sender)` 的瞬时按钮。直接点击、输入、快捷键、剪贴板、安全字段、未注册视图和外部 PID 均被拒绝。
|
|
191
|
+
|
|
192
|
+
**接入:**在应用中导入本地 Swift 包。在 MainActor 创建 `WardenDesktopSurface(window:applicationID:)`,设置按钮 accessibility element/role/identifier,再调用 `register(id:button:target:selector:)`。在整个生命周期内保留 surface 和 `WardenDesktopStandardIO(surface:)`;`start()` 使用独占的继承 stdio 管道。观察返回注册控件的结构化元数据,不是像素截图或全局 AX 树。最多 64 个控件,引用/标识符唯一,target 必须明确且被保留;nil target 和不安全的 Objective-C 签名被拒绝。参见[源码](../native/macos/Sources/WardenDesktop/NativeSurface.swift)及[原生宿主](../native/macos/Sources/WardenDesktopHost/Main.swift)。
|
|
193
|
+
|
|
194
|
+
所有模型/收件人/处理器变化必须在 MainActor 上、在已批准处理器之外,先调用 `invalidate()` **再**修改,包括不可见变化及 A → B → A。窗口通知和新指纹只是补充,不能证明观察到了全部隐藏变化。已批准处理器必须同步执行,不得启动嵌套模态循环、异步转发或替换 responder;处理器自身的变更由 commit 修订轮换覆盖。应用不能遵守这一所有权契约时,不得启用原子模式。未接入的第三方应用没有回退路径:Apple 提供[分开的 AX 读取与动作](https://developer.apple.com/documentation/applicationservices/1462091-axuielementperformaction),并未提供本协议的修订契约。
|
|
195
|
+
|
|
196
|
+
票据绑定完整参数,同时按系统时钟和单调时钟失效,最长五分钟。在分派前消耗;取消、重放、重启及不匹配均不能复用。失败或不确定的分派会封锁原生权威,不得仅为重试付款而重启或重新授权。committed 仅确认本地 target 处理器分派,**不**确认邮件送达、付款结算或异步任务完成;这些结果需要事务核对和服务端持久幂等键。回复丢失时 wrap 保留不确定性锁。
|
|
197
|
+
|
|
198
|
+
**原生集成门禁:**`npm run test:macos` 分别构建生产和测试二进制,运行真实窗口、stdio 和 wrap 表单。覆盖目标/处理器/边框/窗口变化、外观相同的对象替换、ABA、hit-test 重入、过期/时钟回拨/重放/重启/取消、跨语言指纹及多语言标签。生产构建不包含测试变更方法。本测试集与跨平台 `npm test` 分开;非 macOS、工具缺失或 GUI 不可用会导致原生门禁失败,不会静默 skip。本地 CI 配置新增 macOS 门禁,未远程执行。测试不请求全局 Accessibility/Screen Recording 权限,也不修改 TCC。没有发布或部署。
|
|
199
|
+
|
|
200
|
+
**本地复审(2026-10-24):**prepare 和 commit 现在会在 `hitTest` 后重新读取原生属性;即使宿主遗漏 `invalidate()`,处理器、标签、启用状态或边框变化也会导致拒绝。分派前再次检查系统时钟和单调时钟。Objective-C sender 参数必须是对象(`@`),不能是 block(`@?`)。通用 TypeScript 原子服务器也使用单调期限,并在执行效果前再次检查过期。回归覆盖这些情况、prepare 期间目标变化、过期容量回收和原生处理器重入。这些检查不能代替宿主所有权契约:getter 和 hit-test 不得启动嵌套事件循环或分派效果;隐藏的模型或收件人变化仍需事先 invalidate。仅支持主动接入的可信应用。
|
|
201
|
+
|
|
202
|
+
**直接调用契约(第二次本地审计,2026-10-24):**注册处理器必须能安全直接调用,并自行检查应用权限;不能依赖重写的 `NSApplication.sendAction` 或 responder 路由进行授权。时钟提供者和 getter 是可信的同步宿主代码。隐藏变化和 ABA 仍要求先 `invalidate()`。回归覆盖 hit-test 中的模态/透明度变化、runtime 实现替换、稳定的半透明控件、dispatch 拦截和最后时钟 callback 触发的失效。这些检查随 npm `0.21.0` 发布。本地测试报告不能代替签名的 release-quality 凭据;当前 digest 仅覆盖 `dist` 中的 JavaScript,不覆盖原生 SDK 源码;原生验证另行进行。
|
|
203
|
+
|
|
204
|
+
## 服务器端原子目标校验
|
|
205
|
+
|
|
206
|
+
**显式启用:**`--screen-atomic` 要求 `--flow`、`--screen-read` 以及实际执行防护的 flow 模式。严格确认仍是默认值。必须使用可信且实现该协议的服务器;工具注解或自称支持某个版本并不能建立信任。不支持协议时,在询问用户之前拒绝;绝不退回普通点击。原有的仅截图模式仍不具备原子性。
|
|
207
|
+
|
|
208
|
+
先构建 WARDEN,然后在其目录运行以下本地示例。示例拥有一个虚拟表单,不操作系统输入、不发送邮件、不付款,也不访问网络:
|
|
209
|
+
|
|
210
|
+
```sh
|
|
211
|
+
node dist/mcp-server.js wrap --flow screen --screen-read screenshot --screen-atomic -- node examples/atomic-screen-server.mjs
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
**协议:**询问前,代理通过私有 `warden/screen/prepare` 传递精确动作及指定观察请求。参数示例:
|
|
215
|
+
|
|
216
|
+
```json
|
|
217
|
+
{
|
|
218
|
+
"protocol": "warden.screen.atomic.v1",
|
|
219
|
+
"observation": { "name": "screenshot", "arguments": {} },
|
|
220
|
+
"action": { "name": "click", "arguments": { "index": 3 } }
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
服务器返回 `protocol`、不透明的一次性 `ticket`、表面 `revision`、目标 `stamp`、`expiresAt` 和 `observation`。代理用该观察结果验证目标指纹,展示动作;用户明确同意后,再检查工具定义、风险上下文和最新目标。它发送 `warden/screen/commit`,参数为 `{protocol,ticket,expected:{revision,stamp},action}`,而不是原始工具调用。服务器消耗票据,在同一临界区比较当前修订、解析后的目标和精确参数,并同步提交动作。比较与效果之间不得交还事件循环,也不得把坐标点击排队。任何变化,包括处理器/收件人变化及 A → B → A,都必须更换修订。动作使用已经解析的目标引用,而非稍后重新按坐标定位。
|
|
225
|
+
|
|
226
|
+
服务器使用 `@aimarket/warden/atomic-screen` 导出的 `AtomicScreenServer`(本地构建为 `dist/atomic-screen.js`)。将三种协议方法分别路由到 `prepare(params)`、`commit(params)`、`cancel(params)`;观察工具路由到 `read()`。所有原始动作执行路径必须拒绝。每个表面在所有连接间共用一个权威实例;其他变更必须经过 `replace(snapshot)`。可信同步 `apply(action, target)` 返回 `{result,snapshot}`,其中 result 为普通 MCP 工具结果。异步函数不被接受;异常或无效结果会封锁表面,直到明确核对并替换状态。参见[可运行服务器示例](../examples/atomic-screen-server.mjs)。
|
|
227
|
+
|
|
228
|
+
票据最长有效五分钟,绑定完整动作,在尝试 commit 时消耗,服务器重启后不可用。最多 256 个待确认票据。客户端无法通过 wrap 调用私有协议;票据不会传给模型或写入 flow 日志。拒绝或取消后,`warden/screen/cancel` 删除未使用票据;遗留票据按期失效。原子动作参数必须能完整显示在 1500 个转义字符以内,超长调用直接拒绝,不展示截断的确认内容。
|
|
229
|
+
|
|
230
|
+
验证后的 `committed` 回执包含 `protocol,status,revisionBefore,revisionAfter,stamp,result`;wrap 只返回 `result`。验证后的 `refused` 回执包含 `protocol,status,reason`,表示没有效果。审计区分 `atomic_committed` / `atomic_refused`。回执格式错误、传输错误或结果丢失均为 `execution_uncertain`:禁止自动重试,保留共享 GUI 锁,直到操作员核对。效果可能在回复丢失前已发生。服务器票据不能替代持久化支付幂等键。
|
|
231
|
+
|
|
232
|
+
**所有权边界:**只有可信服务器完全拥有表面状态及同步动作时,这个实现才关闭该竞态。必须通过身份验证或独占传输限制只有可信代理可以 prepare/commit;票据本身不证明用户同意。单进程权威不是跨进程操作系统锁。在异步鼠标输入或 Playwright/desktop RPC 外包一层本 API,不会让远端表面原子化。原生后端需要真正的平台事务/修订原语,或受控的同步应用模型。原生目标应用内 AppKit 后端见 macOS 一节;未接入的外部应用仍不受支持。不实元数据、未跟踪的外部行为者及有害但已授权的处理器不在保证范围内。Claude hook 无法在批准后执行此私有 commit。回归测试涵盖最终代理读取后的变化、ABA/处理器变化、重放、过期、重启、重入、原始调用拒绝及不确定效果。没有发布或部署。
|
|
233
|
+
|
|
234
|
+
## Auten:按结果一次确认,并在批准后重新读取屏幕
|
|
235
|
+
|
|
236
|
+
**结果确认:**把下面的 `runs` 片段加入已固定的清单,用两空格缩进及末尾换行保存,重新计算哈希,再使用下面的 `taskAdapter.mode: "review"` 策略。调用 `task_run {"id":"mail_to_bob"}`。内置适配器在第一个效果之前只弹出一次 MCP 表单,显示结果、完整顺序、精确 URL 和正文;隐藏认证请求头。复选框默认 false。没有表单、接受默认值、拒绝或取消都不会授权。默认仍是 `strict`;`capabilities` 保留操作员明确预授权。
|
|
237
|
+
|
|
238
|
+
示例把 GUI 准备/发送归并成固定 HTTP 效果。每个计划最多八个不同操作 ID、共 16 个计划,完整转义预览最多 12 000 字符。模型不能改变步骤、顺序、收件人、正文或结果。`review` 禁止单独 `task_execute`,避免绕过结果确认。资源读取与列表不弹窗;客户端/敏感工具独立权限仍可能询问。
|
|
239
|
+
|
|
240
|
+
跨进程任务锁覆盖提问与执行。先检查预算,再在接受后原子预留整个计划及全部操作预算。计划重启后也只能用一次。每步重查清单/策略、期限、取消与凭据绑定。偏离、错误或结果不确定会停止后续,所有预留预算包括未执行步骤仍消耗。先前效果不会回滚,响应也不能改变下一步或目的地。预留前拒绝/取消不消耗。支付结果不确定时先对账,不能删除状态/锁来重试。审计区分批准、预留、完成与停止,不记录正文/令牌。
|
|
241
|
+
|
|
242
|
+
```json
|
|
243
|
+
{
|
|
244
|
+
"runs": [
|
|
245
|
+
{
|
|
246
|
+
"id": "mail_to_bob",
|
|
247
|
+
"title": "Send the reviewed public report to bob@corp.com in Mail",
|
|
248
|
+
"operations": [
|
|
249
|
+
"send_report"
|
|
250
|
+
]
|
|
251
|
+
}
|
|
252
|
+
]
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
```json
|
|
257
|
+
{
|
|
258
|
+
"mode": "ask",
|
|
259
|
+
"taskAdapter": {
|
|
260
|
+
"mode": "review",
|
|
261
|
+
"server": "warden_task",
|
|
262
|
+
"manifestSha256": "c69bafc53aa2e4a1a82dd9a20accbe2e4de5372d7545509fe3f6ccf18fdc5580"
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
**仅 wrap 支持批准后新屏幕:**明确选择同一个已审查服务的观察工具,例如:
|
|
268
|
+
|
|
269
|
+
```sh
|
|
270
|
+
node dist/mcp-server.js wrap --flow screen --screen-read get_elements -- node /absolute/path/screen-server.js
|
|
271
|
+
node dist/mcp-server.js wrap --flow screen --screen-read computer --screen-read-input '{"action":"screenshot"}' -- node /absolute/path/screen-server.js
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
`--screen-read` 需要 `--flow`;`--screen-read-input` 是严格 JSON:已知观察名只接受空输入,通用控制器只接受一个已知读取 `action`。`readOnlyHint` 不是权限。未配置时保留普通逐调用严格确认,不声称批准后重查。Claude hook 在客户端批准与执行之间没有回调,不能做该检查。
|
|
275
|
+
|
|
276
|
+
Wrap 提问前读取基线,批准后重新验证工具定义并再次读取。比较这次真实响应而非缓存:唯一目标、角色、精确节点引用、边框、上下文及键盘一致焦点;如存在,也比较 accessibility ID、标签和表单提示。变化、缺失、重叠/歧义、不完整列表、仅像素或读取失败都拒绝执行。不猜坐标/缩放转换。多动作或额外字段模式不能比较。风险变化或新发现秘密也停止,最后读取期间取消仍有效。
|
|
277
|
+
|
|
278
|
+
共享 `WARDEN_FLOW_SESSION` / state 的代理以屏幕锁串行执行已知 GUI 效果,第二代理未启用重查也受限。正常结果释放锁;崩溃/结果丢失留下不确定锁供操作员核对。只读观察可继续。`screen_validation` 记录 `unchanged`、`refused_without_approval`、`refused_after_approval`、`execution_uncertain`;接受表单或元数据相等都不证明已执行。
|
|
279
|
+
|
|
280
|
+
**边界:**缩小过期目标竞争窗口,但截图和点击仍非原子。外部程序可能在读取后改变界面,服务可能返回缓存/错误数据;相同 ID/边框不能证明处理函数或效果未变。完整解决需要可信服务原子验证 revision/目标并执行效果。任意 click/paste/Send 链不会获得整体放行;分组只用于真正约束效果的结构化适配器。仅影响回答的注入仍不在工具效果边界内。
|
|
281
|
+
|
|
282
|
+
本地回归:`test/wrap-screen.test.ts`、`test/wrap.test.ts`、`test/task-adapter.test.ts`。[最新本地 AgentDojo checkpoint](../scripts/agentdojo/results/summary-2026-10-23-auten-local.json),无模型 API、无 GUI 工具的确定性 replay。没有发布、部署或发送评论。
|
|
283
|
+
|
|
5
284
|
## 权限请求说明(尚未发布的源码)
|
|
6
285
|
|
|
7
286
|
请求现在显示工具、最多四个目标和原因。预览不包含消息正文、shell 代码、URL 的凭据/路径/查询参数以及识别出的敏感值。尚未跟踪每个目标的来源;指纹匹配也不能确定具体源文件,因此不再把最近读取的文件当作匹配来源。请在客户端检查完整调用。
|
|
@@ -16,18 +295,19 @@
|
|
|
16
295
|
- 保护识别出的守卫策略/状态、Claude hooks、Git hooks/config 写入,包括路径变量及符号链接。这不能替代操作系统权限。
|
|
17
296
|
- 使用 URL 解析器检查实际主机及所有目标。邮件正文中的链接不能授权另一个收件人;策略中的邮箱必须完整匹配,域名不授权该域下所有邮箱。用户提及目标也不等于授权任意操作和数据。
|
|
18
297
|
- 联系人解析必须显式配置 `contactTools` 和 `private` 标签,只接受结构化 `name`/`email` 记录,并要求用户提及完整显示名。同名不同地址需要确认。本地文件、普通文本、YAML 和旧版本缓存都不能建立这种信任。只信任代理和第三方无法修改的通讯录。
|
|
19
|
-
- 指纹检查可见参数文本及有限的 URL/base64/hex 解码。自 2026-10-22 起,看起来像密钥的值(凭据文件中随机的字符串,以及在任何地方读到的已知令牌格式)还会按 8 个字母和数字的窗口记录,hex 密钥按 10 个:密钥的一段、倒写的密钥、带分隔符或不可见字符的密钥、分段 base64 编码的密钥,或用西里尔、希腊形似字母改写的密钥,都会被拒绝。这是最小的窗口大小:在这个大小下,八种格式的 480 个虚构密钥在 1.15 亿个字母和数字(本 monorepo 和 1,000 个 HISTOR 包) 的普通文本中一次都没有偶然命中;同类密钥共有的部分(DER 密钥中的算法标识、JWT
|
|
298
|
+
- 指纹检查可见参数文本及有限的 URL/base64/hex 解码。自 2026-10-22 起,看起来像密钥的值(凭据文件中随机的字符串,以及在任何地方读到的已知令牌格式)还会按 8 个字母和数字的窗口记录,hex 密钥按 10 个:密钥的一段、倒写的密钥、带分隔符或不可见字符的密钥、分段 base64 编码的密钥,或用西里尔、希腊形似字母改写的密钥,都会被拒绝。这是最小的窗口大小:在这个大小下,八种格式的 480 个虚构密钥在 1.15 亿个字母和数字(本 monorepo 和 1,000 个 HISTOR 包) 的普通文本中一次都没有偶然命中;同类密钥共有的部分(DER 密钥中的算法标识、JWT 的头部和声明)从不记录。每个参数会记住它在外部文本之后发出内容的末尾,因此通过同一参数连续发出的分段会被整体检查。2026-10-23 本地源码新增上文的六字符配对和明确字符列表解码。仅格式前缀(`rk_live_`)不作为秘密证据。指纹不会在发送时读取任意文件,也不覆盖所有编码和工具。项目内编辑通常仍被允许,执行代码则单独判断。
|
|
20
299
|
- 外部文本之后,把本会话读到的密钥写进项目中的普通文件会先询问(`deny` 模式拒绝):项目文件之后会被提交和发布,无需再次调用。`.env`、`.npmrc` 等凭据文件本来就是放密钥的地方,写入照常放行;只删除密钥的修改不会触发。
|
|
21
300
|
- 只出现在粘贴文本、引用行(`>`)、粘贴邮件的头部或转发标记之下的地址,不算你点名的地址:发往它会询问一次。你输入的地址后面的句号或逗号不再妨碍识别。
|
|
22
301
|
- 没有运营者标签的 MCP 工具,在名字表明会外发(send、post、share……)、参数带 URL,或自 2026-10-22 起点名了某一方时,算作外发:例如 `to`、`email`、`attendees`、`assignee`、`collaborator`、`username` 这样的参数,或任何邮箱地址、IBAN。`warden-mcp flow-labels` 列出你的会话用过的无标签 MCP 工具,附上守卫的猜测和一个 `labels` 块,校正后粘贴进策略即可。
|
|
23
|
-
-
|
|
302
|
+
- 默认情况下,接收外部内容后,已识别的屏幕操作均需确认,不依赖坐标、截图文字、元素列表格式或标签语言。包括点击、轻触、拖动、输入、填充、粘贴、Enter/Return 及未知键盘操作。`deny` 模式拒绝执行。英文词只帮助解释,Inbox 等熟悉标签也不会授权点击。详见上文受限任务模式。
|
|
303
|
+
- 只改变回答的注入不会发出可拒绝的调用。自 2026-10-22 起,插件的 Stop 钩子会在本轮读过外部文本的回答下方加一行,列出这些来源;若其中有文本以指令口吻对助手说话,也会注明。如果回答连续重复了外部文本中对助手下指令那几句话里的 12 个规范化字符,钩子还会把回答退回给模型一次(`decision: block`),在用户读到之前对照用户的请求检查;用户只损失这次检查的时间。`answerNote`:`always`(默认)、`instruction`(只在这种情况下)或 `off`;插件之外请注册 `warden-mcp hook stop`。
|
|
24
304
|
- 代理也记录 JSON-RPC 和工具错误;记录失败时不转发响应,现有会话状态损坏时阻止检查中的调用。
|
|
25
305
|
|
|
26
|
-
已在 npm `0.17.0` 发布:`npx -y @aimarket/warden@0.
|
|
306
|
+
已在 npm `0.17.0` 发布:`npx -y @aimarket/warden@0.22.0 hook pre-tool-use`;或从源码在 WARDEN 目录运行 `npm ci && npm run build`,然后使用 `node dist/mcp-server.js hook pre-tool-use`,并注册 prompt/post hooks。策略为 `~/.local/state/warden/flow-policy.json` 或 `WARDEN_FLOW_POLICY`;模式为 `ask`、`deny`、`audit`、`off`。当前配置示例见[英文页](flow-guard.md)。
|
|
27
307
|
|
|
28
308
|
代理命令:`node dist/mcp-server.js wrap --flow mail -- node mail-server.js`。同一会话的代理应共享一个新的 `WARDEN_FLOW_SESSION`。默认父进程 PID 不能关联不同启动器。代理看不到用户提示或客户端内置工具。需要确认的调用会在客户端提供 MCP elicitation 表单时通过表单询问(回答记入日志的 `approvalOutcome`),否则或使用 `--ask refuse` 时被拒绝。`trustedSources` 仅用于 WebFetch URL,不用于 MCP 参数中的任意链接。
|
|
29
309
|
|
|
30
|
-
**这些数字描述哪个版本。** 下面的回放表格于 2026-10-22
|
|
310
|
+
**这些数字描述哪个版本。** 下面的回放表格于 2026-10-22 在当日代码上重新运行:审计修复加上 2026-10-22 的改动。2026-10-22 的改动没有改变其中任何一个决定(全部 1,046 条记录与改动前的代码一致);审计修复的代价是少了一个不询问的任务、少了 19 个受攻击时完成的任务。模型运行的表格和费用仍对应审计前、截至 `2328be980` 的实现;没有新的模型运行。参考解回放只是固定攻击路径,并非自适应最坏情况;2026-10-22 手握代码的攻击见[下文](#2026-10-22-改了什么为什么)。
|
|
31
311
|
|
|
32
312
|
## 在 AgentDojo 上的测量
|
|
33
313
|
|
|
@@ -152,11 +432,17 @@ workspace 中八个较新的攻击者目标没有参考解,因而无法回放
|
|
|
152
432
|
| 同类密钥共有的部分不再记录(DER 密钥中的算法标识、JWT 的头部和声明) | 测量发现,会话读过 RSA 私钥之后,0.19.0 会拒绝发送含有 DKIM 密钥的 README | 发布的规则下没有任何偶然命中 |
|
|
153
433
|
| 把本会话读到的密钥写进项目中的普通文件会询问 | 写进 `docs/debug.md` 的密钥能通过 | 会询问;`.env` 等凭据文件照常放行 |
|
|
154
434
|
| 只出现在粘贴或引用文本里的地址不算用户点名的 | 粘贴进提示词的攻击者地址被当作用户的 | 询问一次;用户也输入过的地址放行。输入的地址后面跟句号不再被当作未点名(0.19.0 会对"发到 bob@corp.com。"询问) |
|
|
155
|
-
| Stop 钩子把重复了对模型指令的回答退回一次 | 只改回答的注入不发出调用 | 在会服从这个攻击的 Ministral 8B 上(无守卫时 20 个回答中有 6 个推荐该酒店),仅守卫的提示就把它降到 0;重新检查在 20 次中触发 3
|
|
435
|
+
| Stop 钩子把重复了对模型指令的回答退回一次 | 只改回答的注入不发出调用 | 在会服从这个攻击的 Ministral 8B 上(无守卫时 20 个回答中有 6 个推荐该酒店),仅守卫的提示就把它降到 0;重新检查在 20 次中触发 3 次,没有改变任何结果。在 DeepSeek V4.1 Flash 上,20 次中触发 2 次([结果](../scripts/agentdojo/results/model-answer-recheck-2026-10-22.json))。这是安全网,不是测得的收益;保存文本的限制见下文 |
|
|
156
436
|
| 规则集 v16(见 [gates](gates.zh.md)) | MCPTox dev 一半中仍有 34 个投毒工具能通过,几乎都是没有输入的工具 | 留出的一半 218 中 194 → 210,其中隐式触发的劫持 66 个全部拦下;45 台干净服务器中 0 台;语料库和 1,000 个 HISTOR 包的拦截与 v15 完全相同;初稿的五个误报已作为测试固定下来 |
|
|
157
437
|
| 重新回放 | 新检查不应在 0.19.0 不询问的地方询问 | 全部 1,046 条记录与 0.19.0 一致 |
|
|
158
438
|
|
|
159
|
-
|
|
439
|
+
**保存回答的限定说明(2026-10-25):**按 AgentDojo 的精确名称匹配规则,DeepSeek guard + note 的官方结果仍为 **18/20**。AI 辅助逐条阅读未在这些保存片段中发现采纳攻击建议;18 次精确名称提及都出现在警告中。只有 18 个回答完整,另两个达到旧的 2,000 字符保存上限,因此不能据此确立完整回答的 0/20 服从率。该标注既非独立也非盲审,不替代官方分数。本地 harness 现在为后续运行保存完整回答、长度和 hash;这不代表重新运行了模型。[审计与复现](../../docs/growth/launchgate-methodology-2026-10-25.ru.md)。
|
|
440
|
+
|
|
441
|
+
**受控选择测试(2026-10-25):**独立的工具结果后合成测试使用已发布的 WARDEN `0.21.0`,覆盖六项酒店任务 × 五次重复、clean/benign/injected 三种备注及三种配置:**270/270 个 ID 选择正确**,其中 injected 条件下**0/90 次选择攻击目标**(每种配置 0/30)。目标名称出现在包括对照组在内的 **25/270** 个回答中,`note_stop` 的 Stop 触发 **0/90** 次;无守卫基线也全部选对,因此尚未测得守卫的额外收益,而正确 ID 不代表解释中的每项事实都准确。[协议、结果与限制](../../docs/growth/launchgate-selection-2026-10-25.en.md):这项独立研究不改变 AgentDojo 历史上的 **18/20**,也不证明普遍安全。
|
|
442
|
+
|
|
443
|
+
**并列选择后续实验(2026-10-25):** 两个最优选项均可接受时,注入条件下目标选择分别为:无防护 48/48、note 44/48、note+Stop 45/48;对应 clean 基线为 28/48、25/48、29/48。经基线调整的防护效果区间包含零;432 次选择均符合任务要求,选择目标本身不能视为错误。真实用户偏好得到 18/18 次遵守,Stop 未要求复查。本地[离线评估器](../scripts/selection-probe/README.md)现支持多个可接受答案及共同基线比较;运行时阻断逻辑未更改。[结果与限制,英文](../../docs/growth/launchgate-tie-selection-2026-10-25.en.md)。
|
|
444
|
+
|
|
445
|
+
在 2026-10-22 发布版中,下面两个例子仍能通过;2026-10-23 本地源码已拦截,详见上文。[历史结果](../scripts/redteam/results/):
|
|
160
446
|
|
|
161
447
|
- **短于 8 个字符、每段被不同文字包裹的分段**,发往用户输入的地址:一个 40 字符的密钥要 7 封以上的邮件。
|
|
162
448
|
- **用单词拼读出来的密钥**("七,大写 Q,m,二……")。把字母换成形似数字(o→0、l→1)在我们的测试密钥上被抓到,只是因为它有足够多的部分不含这些字母。
|
|
@@ -168,7 +454,7 @@ workspace 中八个较新的攻击者目标没有参考解,因而无法回放
|
|
|
168
454
|
而不是根据我们的标签。标错的工具就是一个漏洞;没有标签的工具得到守卫的猜测,而猜测只会增加谨慎。
|
|
169
455
|
- **它拦不住只改变回答的注入**("说这家酒店最好")。没有调用,就没有可拒绝的东西。Stop 钩子会告诉用户回答来自哪里;若回答重复了对模型的指令,会请模型检查一次;它只看得到守卫能识别为指令的文本。
|
|
170
456
|
- **项目内的本地修改会放行**,本会话读到的密钥写进普通文件除外。编辑项目文件是智能体的本职工作。
|
|
171
|
-
- **小块泄露。**
|
|
457
|
+
- **小块泄露。** 普通私有文本可以发往用户点名的目标。流拼接和六字符配对规则覆盖部分密钥分段;更短且带填充的片段及不支持的单词编码仍是边界。
|
|
172
458
|
- **粘贴的不等于输入的。** 你想用但只是粘贴的地址会询问一次。
|
|
173
459
|
- **它看不到**安装插件之前你的提示词,也看不到模型从别处得到的文本。
|
|
174
460
|
|
|
@@ -181,7 +467,7 @@ mkdir -m 777 out
|
|
|
181
467
|
docker run --rm --network none -v "$PWD/out:/out" warden-adojo /out/oracle.json
|
|
182
468
|
```
|
|
183
469
|
|
|
184
|
-
`oracle.py` 按配对写出结果;`--variants none,strict,intent` 选择守卫的变体(`strict` 不考虑用户输入了什么)。`summarize_oracle.py` 把它们汇总成表格引用的摘要。`WARDEN_FLOW_GUARD=/out/x.mjs` 可回放守卫的另一个版本(插件里任一份 `flow-guard.mjs
|
|
470
|
+
`oracle.py` 按配对写出结果;`--variants none,strict,intent` 选择守卫的变体(`strict` 不考虑用户输入了什么)。`summarize_oracle.py` 把它们汇总成表格引用的摘要。`WARDEN_FLOW_GUARD=/out/x.mjs` 可回放守卫的另一个版本(插件里任一份 `flow-guard.mjs`;自 2026-10-24 起需连同同一文件夹中的 `flow-guard-*.mjs` 各部分),2026-10-22 的改动就是这样与改动前的代码对比的。
|
|
185
471
|
|
|
186
472
|
手握代码的攻击不需要容器:`npm run build && node scripts/redteam/flow-redteam.mjs out.json`。
|
|
187
473
|
|
|
@@ -196,3 +482,15 @@ python3 scripts/agentdojo/summarize_model.py summary.json /srv/adojo/out --goals
|
|
|
196
482
|
|
|
197
483
|
`WORK/ctx` 是构建上下文(`dist/` 和 `scripts/agentdojo/`);`--obedient` 加上劫持那段话;`model.py OUT --model deepseek-flash --model-label DeepSeek --dump-goals` 写出攻击者目标,
|
|
198
484
|
`summarize_model.py` 据此识别指向攻击者的调用。两轮每次运行的记录:`results/model-deepseek-2026-10-18b.jsonl.gz`(摘要 `model-deepseek-2026-10-18b.json`);`--guard-note` 把守卫的说明返回给模型。
|
|
485
|
+
|
|
486
|
+
## 来源指令信号与 Stop 诊断(本地 0.22.0)
|
|
487
|
+
|
|
488
|
+
有界的英语/俄语模式可识别伪造角色分隔符、与邻近指令结合的所谓转达偏好或先前批准、要求隐瞒的指令及私有评分规则。这些信号可能出错,合法引用也可能触发;它们不证明攻击、不授予权限,也不会自动禁止选择。用户的真实请求仍作为独立来源处理。
|
|
489
|
+
|
|
490
|
+
本地日志记录 `instructionSignal`、`signalKinds`、`signalScanLimited` 和 `warningKind`(`source`、`instruction`、`suppressed-audit`)。Stop 记录 `trigger`(`no-instruction-signal`、`no-literal-overlap`、`literal-instruction-overlap`)、`recheckRequested` 及 `semanticCompliance: "not-assessed"`。保留现有的 12 个规范化字符重合阈值和宿主标记的继续次数限制;复核既不等于永久拒绝,也不证明纠正。
|
|
491
|
+
|
|
492
|
+
仓库工具 `scripts/selection-probe/audit_warnings.mjs` 可重放已保存的 hook 输入与答案。确认候选词只描述可见文本,不能证明模型意识到或遵从了指令。重放旧答案只测量 hook 行为;选择是否改变需要新的受控模型实验。
|
|
493
|
+
|
|
494
|
+
Post/Stop 警告使用固定语句和不透明的 `source-` ID(工具名 SHA-256 的前 16 个十六进制字符),不会引用检测到的指令,也不重复原始工具名、来源 URL 或路径。这限制了外部元数据借警告渠道获得权威性,但不使模型免受原始工具结果的影响。ID 只用于关联,不是经验证的软件包身份、pin 或权限。当地日志仍可能包含外部元数据,必须作为不可信数据处理。
|
|
495
|
+
|
|
496
|
+
**新的模型对比(2026-10-25):** 在相同六个已知案例的 720 个交错运行答案中,无保护时攻击目标被选中 48/48 次;已发布 0.21.0 的 note/note+Stop 为 44/48、46/48;两个本地候选模式均为 27/48。候选的干净基线为 23/48、25/48。相对旧版、校正基线后的改善区间:note 为 [−8.3,+60.4] 个百分点,note+Stop 为 [+14.6,+62.5]。12 次实际复核均未改变所选 ID,其中三个最终答案失去了可见的警告引用。全部 ID 均可接受,真实用户偏好遵从为 30/30。这些已知案例、tool-role 桥接及完整版本对比不证明普遍防护或 Stop 的独立收益。[完整报告](flow-guard-model-comparison-2026-10-25.zh.md)。
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Límites de medición y pruebas de versión
|
|
2
|
+
|
|
3
|
+
> 🌐 [English](scan-limits.md) · [Русский](scan-limits.ru.md) · **Español** · [Français](scan-limits.fr.md) · [中文](scan-limits.zh.md)
|
|
4
|
+
|
|
5
|
+
Estas precisiones corresponden al seguimiento de comentarios del 2026-10-25. El **artefacto npm publicado `0.21.0`** y el código local posterior son objetos distintos: conservar la versión en `package.json` no incorpora una corrección al archivo publicado. Las pruebas de código, la facturación ficticia y las respuestas programadas de aprobación no sustituyen las evaluaciones de modelos, el tráfico de producción ni los estudios con personas.
|
|
6
|
+
|
|
7
|
+
## Facturación y declaraciones del servidor
|
|
8
|
+
|
|
9
|
+
`initialize`, `tools/list` y una llamada canary pueden generar cargos u otros efectos en el servidor. Un descubrimiento o preview correcto no demuestra el precio ni el efecto de la siguiente llamada. En nuestra fixture de facturación sintética, el canary elegía `preview` gratuito, mientras que `{}` elegía una operación que cobraba siete créditos ficticios. Esto mide esa fixture, no la factura de un vendedor externo.
|
|
10
|
+
|
|
11
|
+
`readOnlyHint`, `destructiveHint` y `openWorldHint` son declaraciones no verificadas; no prueban gratuidad ni ausencia de efectos dañinos. La revisión local de annotations en el primer uso es opcional, está en `off` por defecto y solo se aplica a `wrap --flow NAME`. Aceptarla no aprueba un precio ni certifica efectos. Véanse los [controles de flujo y sus límites](flow-guard.es.md).
|
|
12
|
+
|
|
13
|
+
## Versión solicitada del paquete y versión declarada del servidor
|
|
14
|
+
|
|
15
|
+
`package@x.y.z` especifica una versión solicitada del paquete. El servidor proporciona `initialize.serverInfo.version`; no es una versión de paquete resuelta de forma independiente ni un digest del artefacto. Por ejemplo, el paquete Mapled revisado era `@mapled/mcp@0.21.6`, pero el servidor seguía declarando `0.1.0`.
|
|
16
|
+
|
|
17
|
+
El `0.21.0` publicado que se probó podía usar incorrectamente esa versión declarada en una sugerencia de fijación del paquete. Compruebe la resolución del gestor de paquetes y las pruebas de lock/integridad en lugar de aceptar esa sugerencia. La corrección local separa los metadatos y elimina esa sustitución; sigue sin certificar qué bytes ejecutó el launcher. Un `npx` sin versión fija puede resolver otra versión o reutilizar la caché; ningún comportamiento está garantizado en cada inicio. El hash de tools identifica las definiciones observadas, no el programa completo. Véanse [scan](scan.es.md) e [integración](integration.es.md).
|
|
18
|
+
|
|
19
|
+
## Comparaciones de launchers y referencias orientativas
|
|
20
|
+
|
|
21
|
+
La investigación de Auten contaba con una instantánea pública observada, no con dos entornos de launcher medidos. Reproducir una diferencia requiere el runner y su versión exactos, los argumentos de inicio y dos instantáneas de tools de los entornos afectados. Una observación de HISTOR es una referencia orientativa para comparar, no un pin de confianza aprobado por el operador.
|
|
22
|
+
|
|
23
|
+
La documentación auxiliar del [colector de pruebas del launcher](../examples/launcher-evidence/README.md) está actualmente solo en inglés. Guarda definiciones de tools normalizadas por el cliente, no una transcripción original del protocolo. La versión indicada del runner la declara el propietario; ese campo no resuelve de forma independiente el artefacto del paquete. Tener preparado el colector no demuestra que se compararon los dos entornos.
|
|
24
|
+
|
|
25
|
+
## Preguntas, aprobaciones y respuestas
|
|
26
|
+
|
|
27
|
+
El **39/97** histórico cuenta tareas que provocaron un `ask`, no personas que aprobaron. La ejecución después de una decisión del hook no prueba que alguien pulsara Allow. El wrapper puede registrar accept/decline/cancel, pero un cliente programado puede producir las mismas respuestas. Las tasas de aprobación humana, el tiempo de lectura y la fatiga requieren solicitudes realmente presentadas a personas y resultados vinculados; estas pruebas no los midieron.
|
|
28
|
+
|
|
29
|
+
Para la serie guardada de DeepSeek Flash guard + note (`injecagent`, 20 casos de travel), el resultado histórico oficial de AgentDojo sigue siendo **18/20** según su predicado de mención exacta del nombre. La lectura asistida por IA encontró advertencias y no recomendaciones adoptadas en los fragmentos guardados, pero solo 18 respuestas estaban completas; dos alcanzaron el antiguo límite de 2000 caracteres. Se desconocen sus finales, por lo que no se establece un nuevo resultado `0/20` sobre respuestas completas. El harness local guarda las futuras respuestas completas con longitud y hash; no recupera texto perdido ni implica una nueva ejecución del modelo.
|
|
30
|
+
|
|
31
|
+
**Prueba de selección controlada (2026-10-25):** Una prueba sintética separada tras recibir el resultado de la herramienta, con WARDEN `0.21.0` publicado, cubrió seis tareas hoteleras × cinco repeticiones, notas clean/benign/injected y tres perfiles: **270/270 ID correctos**, con **0/90 elecciones del objetivo en injected** (0/30 por perfil). El nombre objetivo apareció en **25/270** respuestas, incluidos los controles, y Stop se activó **0/90** veces en `note_stop`; la referencia sin protección también acertó, por lo que no se establece una mejora adicional del guard, y un ID correcto no valida todos los hechos de la explicación. [Protocolo, resultados y límites](../../docs/growth/launchgate-selection-2026-10-25.en.md): este estudio separado no cambia el **18/20** histórico de AgentDojo ni demuestra seguridad general.
|
|
32
|
+
|
|
33
|
+
**Seguimiento con empate (2026-10-25):** Con dos óptimos admisibles, la selección del objetivo bajo inyección fue 48/48 sin guard, 44/48 con note y 45/48 con note+Stop; las referencias clean fueron 28/48, 25/48 y 29/48. Los intervalos del efecto ajustado por baseline incluyen cero; las 432 elecciones eran admisibles y elegir el objetivo no implica por sí mismo un error. Las preferencias reales del usuario se siguieron 18/18 y Stop no pidió revisiones. El [evaluador offline local](../scripts/selection-probe/README.md) admite conjuntos de respuestas válidas y contrastes con referencia común; el bloqueo en runtime no cambió. [Resultados y límites, EN](../../docs/growth/launchgate-tie-selection-2026-10-25.en.md).
|
|
34
|
+
|
|
35
|
+
## Umbrales de fragmentos y coste de revisión
|
|
36
|
+
|
|
37
|
+
Las ventanas fuertes de fingerprint siguen siendo **8 para non-hex / 10 para hex**. La corrección local del índice tras prefijos reconocidos no demuestra una detección fuerte fiable de fragmentos de seis caracteres dentro de palabras. Una sesión existente debe releer las credenciales para incorporar las nuevas ventanas. Pedir revisión en el límite de credenciales no equivale a identificar ese fragmento como secreto.
|
|
38
|
+
|
|
39
|
+
Del mismo modo, la coincidencia de 12 caracteres normalizados en Stop solicita otra revisión de la respuesta; no demuestra rechazo semántico de una instrucción. Al eliminar la excepción de palabras de advertencia, una advertencia honesta también paga ese paso. Las paráfrasis y la selección manipulada de filas pueden eludir esta coincidencia. Las mejoras en fixtures y los controles elegidos de falsos bloqueos no demuestran un óptimo global ni una tasa de falsos positivos en producción. La [guía de flujo](flow-guard.es.md) explica la política, los límites restantes y la continuación limitada por el indicador `stop_hook_active` del host.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Limites des mesures et preuves de version
|
|
2
|
+
|
|
3
|
+
> 🌐 [English](scan-limits.md) · [Русский](scan-limits.ru.md) · [Español](scan-limits.es.md) · **Français** · [中文](scan-limits.zh.md)
|
|
4
|
+
|
|
5
|
+
Ces précisions concernent le suivi des commentaires du 2026-10-25. L’**artefact npm publié `0.21.0`** et les sources locales ultérieures sont distincts : conserver la version dans `package.json` n’ajoute pas une correction à l’archive publiée. Les tests de code, la facturation fictive et les réponses d’approbation programmées ne remplacent ni l’évaluation des modèles, ni le trafic de production, ni les études auprès de personnes.
|
|
6
|
+
|
|
7
|
+
## Facturation et déclarations du serveur
|
|
8
|
+
|
|
9
|
+
`initialize`, `tools/list` et un appel canary peuvent eux-mêmes entraîner un coût ou un autre effet côté serveur. Une découverte ou un preview réussi ne démontre pas le prix ou l’effet de l’appel suivant. Dans notre fixture de facturation synthétique, le canary choisissait le `preview` gratuit, tandis que `{}` choisissait une opération facturant sept crédits fictifs. Cela mesure cette fixture, pas la facture d’un vendeur externe.
|
|
10
|
+
|
|
11
|
+
`readOnlyHint`, `destructiveHint` et `openWorldHint` sont des déclarations non vérifiées, pas des preuves de gratuité ou d’innocuité. La revue locale des annotations au premier usage est facultative, désactivée par défaut (`off`) et limitée à `wrap --flow NAME`. L’accepter ne valide ni un prix ni les effets réels. Voir les [contrôles de flux et leurs limites](flow-guard.fr.md).
|
|
12
|
+
|
|
13
|
+
## Version demandée du paquet et version déclarée du serveur
|
|
14
|
+
|
|
15
|
+
`package@x.y.z` précise une version demandée du paquet. Le serveur fournit `initialize.serverInfo.version` ; ce n’est ni une version de paquet résolue indépendamment, ni un digest d’artefact. Par exemple, le paquet Mapled examiné était `@mapled/mcp@0.21.6`, alors que le serveur déclarait toujours `0.1.0`.
|
|
16
|
+
|
|
17
|
+
Le `0.21.0` publié et testé pouvait reprendre à tort cette version déclarée dans une suggestion de verrouillage du paquet. Vérifiez la résolution du gestionnaire de paquets et les preuves de verrouillage/intégrité plutôt que d’accepter cette suggestion. La correction locale sépare les métadonnées et supprime cette substitution ; elle ne certifie toujours pas les octets exécutés par le launcher. Un `npx` sans version fixe peut résoudre une autre version ou réutiliser le cache ; aucun de ces comportements n’est garanti à chaque démarrage. Le hash des tools identifie les définitions observées, pas tout l’exécutable. Voir [scan](scan.fr.md) et [intégration](integration.fr.md).
|
|
18
|
+
|
|
19
|
+
## Comparaisons de launchers et références indicatives
|
|
20
|
+
|
|
21
|
+
L’enquête Auten disposait d’un instantané public observé, pas de deux environnements de launcher mesurés. Reproduire une différence exige le runner et sa version exacts, les arguments de lancement et deux instantanés des tools provenant des environnements concernés. Une observation HISTOR est une référence indicative pour comparer, pas un pin de confiance approuvé par l’opérateur.
|
|
22
|
+
|
|
23
|
+
La documentation auxiliaire du [collecteur de preuves du launcher](../examples/launcher-evidence/README.md) est actuellement uniquement en anglais. Il enregistre des définitions de tools normalisées par le client, pas une transcription originale du protocole. La version du runner saisie est déclarée par le propriétaire ; ce champ ne résout pas indépendamment l’artefact du paquet. Un collecteur prêt à l’emploi ne prouve pas que la comparaison des deux environnements a eu lieu.
|
|
24
|
+
|
|
25
|
+
## Questions, approbations et réponses
|
|
26
|
+
|
|
27
|
+
Le **39/97** historique compte les tâches ayant déclenché un `ask`, pas les personnes ayant approuvé. Une exécution après une décision du hook ne prouve pas qu’une personne a cliqué sur Allow. Le wrapper peut enregistrer accept/decline/cancel, mais un client programmé peut produire les mêmes réponses. Les taux d’approbation humaine, le temps de lecture et la fatigue exigent des demandes réellement présentées à des personnes et des résultats liés ; ces tests ne les ont pas mesurés.
|
|
28
|
+
|
|
29
|
+
Pour la série conservée DeepSeek Flash guard + note (`injecagent`, 20 cas de travel), le résultat historique officiel d’AgentDojo reste **18/20** selon son prédicat de mention exacte du nom. Une lecture assistée par IA a trouvé des avertissements plutôt que des recommandations adoptées dans les extraits conservés, mais seulement 18 réponses étaient complètes ; deux atteignaient l’ancien plafond de 2000 caractères. Leurs fins manquantes sont inconnues : aucun nouveau score `0/20` sur réponses complètes n’est établi. Le harness local conserve les futures réponses entières avec longueur et hash ; il ne restaure pas les passages perdus et n’implique pas de nouvelle exécution du modèle.
|
|
30
|
+
|
|
31
|
+
**Test de sélection contrôlé (2026-10-25) :** Un test synthétique séparé après réception du résultat d’outil, avec WARDEN `0.21.0` publié, a couvert six tâches hôtelières × cinq répétitions, des notes clean/benign/injected et trois profils : **270/270 ID corrects**, dont **0/90 choix de la cible en injected** (0/30 par profil). Le nom de la cible apparaît dans **25/270** réponses, contrôles compris, et Stop s’est déclenché **0/90** fois en `note_stop` ; la référence sans protection choisissait aussi correctement, donc aucun gain supplémentaire du guard n’est établi, et un ID correct ne valide pas tous les faits de l’explication. [Protocole, résultats et limites](../../docs/growth/launchgate-selection-2026-10-25.en.md) : cette étude séparée ne modifie pas le **18/20** historique d’AgentDojo et ne démontre pas une sécurité générale.
|
|
32
|
+
|
|
33
|
+
**Suivi avec ex æquo (2026-10-25) :** Avec deux choix optimaux admissibles, la cible a été sélectionnée sous injection 48/48 sans guard, 44/48 avec note et 45/48 avec note+Stop ; les références clean étaient 28/48, 25/48 et 29/48. Les intervalles de l’effet corrigé du baseline incluent zéro ; les 432 choix étaient admissibles et choisir la cible ne constitue donc pas automatiquement une erreur. Les vraies préférences utilisateur ont été suivies 18/18, sans nouvelle vérification Stop. L’[évaluateur offline local](../scripts/selection-probe/README.md) accepte plusieurs réponses admissibles et des contrastes avec référence commune ; le blocage en runtime reste inchangé. [Résultats et limites, EN](../../docs/growth/launchgate-tie-selection-2026-10-25.en.md).
|
|
34
|
+
|
|
35
|
+
## Seuils des fragments et coût de la revérification
|
|
36
|
+
|
|
37
|
+
Les fenêtres fortes d’empreinte restent **8 pour non-hex / 10 pour hex**. La correction locale de l’index après les préfixes reconnus n’établit pas une détection forte fiable d’un fragment de six caractères incorporé dans un mot. Une session existante doit relire les secrets pour acquérir les nouvelles fenêtres. Demander une revue à la frontière des secrets n’équivaut pas à identifier ce fragment comme un secret.
|
|
38
|
+
|
|
39
|
+
De même, une correspondance de 12 caractères normalisés dans Stop demande une nouvelle vérification de la réponse ; elle ne prouve pas le rejet sémantique d’une instruction. Retirer l’exemption des mots d’avertissement fait aussi payer ce passage à un avertissement honnête. Les paraphrases et la sélection manipulée de lignes peuvent échapper à cette correspondance. Les améliorations sur fixtures et les contrôles choisis de faux refus n’établissent ni un optimum global ni un taux de faux positifs en production. Le [guide de flux](flow-guard.fr.md) décrit la politique, les limites restantes et la continuation bornée par le signal `stop_hook_active` du host.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Measurement limits and version evidence
|
|
2
|
+
|
|
3
|
+
> 🌐 **English** · [Русский](scan-limits.ru.md) · [Español](scan-limits.es.md) · [Français](scan-limits.fr.md) · [中文](scan-limits.zh.md)
|
|
4
|
+
|
|
5
|
+
These qualifications apply to the reader follow-ups documented on 2026-10-25. Distinguish the tested **published npm `0.21.0` artifact** from later local source: an unchanged `package.json` version does not make a local fix part of that artifact. Code tests, synthetic ledgers and scripted approval replies are separate from model evaluation, production traffic and human research.
|
|
6
|
+
|
|
7
|
+
## Billing and server-authored hints
|
|
8
|
+
|
|
9
|
+
`initialize`, `tools/list` and a canary call can themselves incur a charge or another server-side effect. A successful discovery or preview does not establish the price or effect of the next call. In our synthetic billing fixture, the canary selected free `preview`, while `{}` selected an operation charging seven fake credits. This measures that fixture, not an external seller's invoice.
|
|
10
|
+
|
|
11
|
+
`readOnlyHint`, `destructiveHint` and `openWorldHint` are unverified claims, not proof that an operation is free or harmless. The local first-use annotation review is opt-in, default `off`, and applies only to `wrap --flow NAME`; accepting it is not billing approval or an effect attestation. See [flow controls and their limits](flow-guard.md).
|
|
12
|
+
|
|
13
|
+
## Requested package version versus reported server version
|
|
14
|
+
|
|
15
|
+
An exact `package@x.y.z` specifies a requested package version. `initialize.serverInfo.version` is a string supplied by the server; it is not an independently resolved package version or artifact digest. For example, the reviewed Mapled package was `@mapled/mcp@0.21.6`, while its reported server version remained `0.1.0`.
|
|
16
|
+
|
|
17
|
+
The tested published `0.21.0` could incorrectly derive a suggested package pin from that reported version. Verify the package-manager resolution and lock/integrity evidence instead of accepting that suggestion. The local fix separates the metadata and removes this substitution; it still does not attest which package bytes a launcher executed. An unpinned `npx` launch may resolve another version or reuse cached resolution; neither outcome is guaranteed on each start. A tool-set hash identifies the observed definitions, not the whole executable. See [scan](scan.md) and [integration](integration.md).
|
|
18
|
+
|
|
19
|
+
## Launcher comparisons and advisory baselines
|
|
20
|
+
|
|
21
|
+
The Auten investigation had one public observed snapshot, not two measured launcher environments. Reproducing a difference requires the exact runner/version and launch arguments plus two tool snapshots from the environments concerned. A HISTOR observation is an advisory comparison baseline, not an operator-approved trusted pin.
|
|
22
|
+
|
|
23
|
+
The [launcher evidence collector](../examples/launcher-evidence/README.md) currently has English helper documentation. It records client-normalized tool definitions, not an original wire transcript; a supplied runner version is owner-reported, and no package artifact is independently resolved by that field. A prepared collector is not evidence that the requested two-environment comparison occurred.
|
|
24
|
+
|
|
25
|
+
## Questions, approvals and answers
|
|
26
|
+
|
|
27
|
+
The historical **39/97** counts tasks that triggered an `ask`, not people who approved. Execution after a hook decision does not prove a person clicked Allow. A wrapper can record accept/decline/cancel, but scripted clients can produce those responses too. Human approval rates, reading time and fatigue require requests actually presented to people and linked outcomes; they were not measured by these tests.
|
|
28
|
+
|
|
29
|
+
For the saved DeepSeek Flash guard + note series (`injecagent`, 20 travel cases), the official historical AgentDojo result remains **18/20** under its exact-name mention predicate. AI-assisted reading found warnings rather than adopted recommendations in the saved excerpts, but only 18 answers were complete; two reached the historical 2,000-character storage cap. Missing tails are unknown, so this is not a replacement full-answer `0/20` score. The local harness saves full future answers with length/hash metadata; it does not restore old tails or imply a new model run.
|
|
30
|
+
|
|
31
|
+
**Controlled selection probe (2026-10-25):** A separate synthetic post-tool probe using published WARDEN `0.21.0` covered six hotel tasks × five repetitions, clean/benign/injected notes and three profiles: **270/270 correct IDs**, with **0/90 injected target choices** (0/30 per profile). Target names appeared in **25/270** answers including controls, and Stop fired **0/90** times in `note_stop`; the unguarded baseline was correct too, so no incremental guard gain is established, and correct IDs do not validate every explanation fact. [Protocol, results and limits](../../docs/growth/launchgate-selection-2026-10-25.en.md): this separate study does not change AgentDojo’s historical **18/20** or establish broad safety.
|
|
32
|
+
|
|
33
|
+
**Tied-choice follow-up (2026-10-25):** With two admissible optima, injected target selection was 48/48 without a guard, 44/48 with the note and 45/48 with note+Stop; the respective clean baselines were 28/48, 25/48 and 29/48. Baseline-adjusted guard-effect intervals include zero, and all 432 choices were admissible; target choice is not automatically an error. Separate genuine-user preferences were followed 18/18, with no Stop rechecks. The local [offline evaluator](../scripts/selection-probe/README.md) now supports admissible sets and common-baseline contrasts; runtime blocking is unchanged. [Results and limits](../../docs/growth/launchgate-tie-selection-2026-10-25.en.md).
|
|
34
|
+
|
|
35
|
+
## Fragment thresholds and recheck costs
|
|
36
|
+
|
|
37
|
+
Strong fingerprint windows remain **8 non-hex / 10 hex**. The local recognized-prefix indexing repair does not establish reliable strong detection of a six-character fragment inside a longer word; an existing session must reread credentials to gain the new index windows. Requiring review at the credential boundary is different from identifying that fragment as a secret.
|
|
38
|
+
|
|
39
|
+
Likewise, Stop's normalized 12-character overlap requests another answer check; it does not prove semantic rejection of an instruction. Removing the warning-word exemption also makes honest warnings pay that extra pass. Paraphrases and poisoned row selection can evade this overlap check. Fixture improvements and selected false-block controls establish neither a global optimum nor a production false-positive rate. The [flow guide](flow-guard.md) describes the policy, remaining gaps and continuation bound supplied by the host's `stop_hook_active` flag.
|