【免费下载链接】aos-ce
AOS Community Edition: the open agent operating system.
本文以 AOS Community Edition 作者手册中的 security 章节(capsules/capsule-forge/src/guides/security.md)为主体,系统讲解在 AOS(Unicity AOS)上开发 capsule 时的安全工程方法:哪些输入必须视为不可信、如何在 capsule 边缘做防御性校验、策略链为何必须 fail-closed、如何在有限的运行时资源边界内设计、如何隔离 principal、如何管理供应链与安装信任,以及按后果严重程度分层做评估和对抗式代码评审的完整问题清单。读完后你应当能够为自研 capsule 建立一套可验证的“边界 + 门控”设计,并对照仓库中的真实实现(capsule-forge、aos-mcp-broker)逐条核对。
这份指南在仓库中的位置与阅读方式
security 章节是 capsule-forge 内置的“作者手册”(author manual)之一。从源码结构看,capsules/capsule-forge/src/lib.rs 中定义了GUIDE_CHAPTERS静态章节表,每个章节通过include_str!将 Markdown 文件编译进 capsule 二进制:
// capsules/capsule-forge/src/lib.rs GuideChapter { topic: "security", summary: "untrusted inputs, failure semantics, limits, reliability, evaluation, and review", content: include_str!("guides/security.md"), },模型或开发者可以通过forge_guide工具以topic: "security"按需加载该章节,而不是把整本手册一次性塞进上下文——这是一种渐进式信息披露(progressive disclosure)的设计。capsules/capsule-forge/src/lib.rs 中的测试author_manual_is_progressive_and_complete还强制要求每一章正文不少于 35 行,即“不允许把安全章节写薄”。这一点值得借鉴:安全指南本身也被当作需要被测试守护的产品资产。
capsule-forge 自身的清单 capsules/capsule-forge/Capsule.toml 也是一个最小化的能力示例:只声明fs_read = ["home://"],加上工具总线必需的 publish/subscribe ACL 条目(tool.v1.execute.*.result等),体现了“能力即显式授权”的基本盘。
信任边界:先划定“什么是不可信的”
指南的第一节给出了一份明确的不可信输入清单。除非内核或运维方(operator)另有证明,以下对象一律按不可信处理:
- LLM 的工具参数与提示文本(tool arguments and prompt text);
- capsule 清单(manifest)与打包资产路径;
- 外部 API 的响应、文件与平台事件;
- 载荷中携带的身份字符串(identity strings carried inside payloads);
- 生成的源码与被建议的能力(suggested capabilities);
- 其他 capsule 的普通数据输出。
而真正“可执行”(enforceable)的边界只有这几类:内核盖戳的主体归属(kernel-stamped principal attribution)、经过验证的内容身份(verified content identity)、清单门控(manifest gates)、主题 ACL、principal 授权(principal grants)以及同意(consent)。
仓库中的实现对这一定位有多处印证:
- capsules/capsule-forge/src/guides/manifest.md 开篇即声明“The manifest is untrusted declarative input”(清单是不可信的声明式输入),运行时负责把它解释为最大权限上限;
- crates/aos-mcp-broker/src/policy.rs 中策略判定结果
Decision::Deny { reason }的注释强调reason“由构造保证净化(Sanitized by construction: operator string, no reflected args)”——即拒绝理由只引用规则自身的 id(运维方写的字符串),绝不回显(reflect)来自不可信参数的内容,避免参数注入进入错误消息; - 载荷里“自称是另一个 principal”的字段在任何位置都不构成授权,这与“身份字符串不可信”的条目一一对应。
实践要点:不要把“我信任这个模型”“这个字段是内部生成的”写进安全论证。论证只能落在上面那六类可执行边界上;其余一切默认敌对。
在 Capsule 边缘做校验:先于主机调用失败
指南第二节要求:在发起主机(host)调用之前,先把空值、畸形值、超大值拒掉。具体规则包括:
- 当参数应当是“一个安全的路径分量(one safe component)”时,拒绝
/、\\、..、NUL、URL scheme 以及绝对路径; - 解析 URL 后,将归一化(normalized)的主机名与预期域名集合比对,而不是做字符串前缀匹配;
- 进程参数一律以 argv 形式传递,绝不把不可信文本插值进 shell 命令;
- 对循环、递归、集合规模、响应大小、重试次数全部设上限;
- 对敏感操作认证内核盖戳的调用方身份;
- 避免把密钥(secret)反射到错误信息、日志、工具输出或 trace 中。
指南特别说明:VFS 与主机门控依然会各自执行边界检查;本地校验的价值在于让模型拿到清晰的失败信号,并在主机调用之前就保护住领域不变量(domain invariants)。
仓库里就有该原则的直接实现。capsule-forge 的validate_name函数(capsules/capsule-forge/src/lib.rs):
/// Reject empty names and path-traversal characters in untrusted name args. fn validate_name(name: &str) -> Result<(), SysError> { if name.is_empty() { return Err(SysError::ApiError("Name cannot be empty".into())); } if name.contains('/') || name.contains('\\') || name.contains("..") { return Err(SysError::ApiError( "Invalid name — path traversal rejected".into(), )); } Ok(()) }该函数被scaffold_capsule、explain_interface、capsule_doctor三个工具入口调用(capsules/capsule-forge/src/lib.rs),拒绝的正是“空、路径穿越字符”这类模型可能随手生成的参数。错误消息也是固定文案,不回显任何用户输入——同时满足“拒绝危险模式”与“不把不可信文本反射进错误”两条规则。
同文件中suggest_capabilities还有一个容易被忽略的安全细节(capsules/capsule-forge/src/lib.rs):当意图描述中出现“no identity operations”“without http”这类否定句式时,mentions_positive/occurrence_is_negated会识别否定并避免凭空生成对应的能力请求行。测试capability_suggestions_ignore_plain_negation(capsules/capsule-forge/src/lib.rs)专门断言:对含否定的意图,输出中不得出现identity =或net =。这对应了信任边界清单中“生成的源码与被建议的能力是不可信的”——建议只是候选,能力必须由作者显式确认。
Fail-Closed:策略层的错误不是拒绝
第三节是全文最容易被实现错误的部分。规则只有两句,但后果严重:
- 主机能力检查与 ACL 检查天然 fail-closed;
- 当 capsule 逻辑本身是策略决策点时,它也必须 fail-closed。
关键在于有序拦截器链(ordered interceptor chain)中的错误语义:
- 返回普通错误(
Err):问题被记录日志,链继续执行; - 意图阻断请求的策略 capsule:必须返回
InterceptResult::Deny { reason }。
指南的原文警告:“测试这个行为;一个Err不是拒绝(anErris not a denial)。” 此外,可选 import 与尽力而为(best-effort)的后台工作,只有在降级行为被显式声明且安全时才合法。
仓库的 capsules/capsule-forge/src/guides/ipc.md(IPC 章节)给出了该语义的完整定义,可作为安全章节的配套参考:
- 同等优先级的匹配处理器之间是独立并发扇出(concurrent fan-out);
- 一旦任何匹配优先级不同,整个匹配集合变成一个按优先级升序执行的有序中间件链;
- 在有序链中:
Continue(非空 payload)替换下一层的 payload;Final(payload)终止链并返回最终结果;Deny { reason }以“拒绝”终止链;NotSupported继续到下一层;普通 handler 错误只记日志,链继续——“That last rule is fail-open for middleware errors. A security or policy layer must returnDeny, notErr, when it intends to block an action.”(最后一条规则对中间件错误而言是 fail-open 的;安全/策略层若要阻断动作,必须返回Deny而非Err)。
也就是说,优先级赋值本身是一个架构决策:新增一个不同优先级,可能把所有并发订阅者悄悄改造成中间件链。指南给出的参考分层(capsules/capsule-forge/src/guides/ipc.md):
10 validate and normalize 20 enforce policy (return Deny on refusal) 50 enrich context 100 execute provider策略层应放在执行层之前,并且它的评审清单明确包含“policy refusal returnsDenyrather than an ordinary error”。capsules/capsule-forge/src/lib.rs 中的测试ipc_manual_explains_priority_mode_switch_and_fail_open_errors甚至断言 IPC 章节必须保留“must returnDeny, notErr”这句话——文档语义同样被测试锁定。
仓库中还有一处更底层的对照实现:MCP broker 的策略决策点(crates/aos-mcp-broker/src/policy.rs):
/// Evaluate `rules` against one tool call. First-match-wins over the /// ordered list; the default is [`Decision::Allow`] so the PDP only ever /// narrows the surface the capability PEP already guards. pub(crate) fn evaluate(rules: &[Rule], tool_name: &str, arguments: &Value) -> Decision { for rule in rules { // ... 按顺序匹配,命中即返回 Allow / Deny { reason: rule.id } } Decision::Allow }这里的设计值得注意:策略 PDP(决策点)默认Allow,因为它是在能力 PEP(执行点,即内核能力强制层)之上再收窄的过滤层——真正的兜底 fail-closed 行为由能力层保证。这与 security 章节“主机能力与 ACL 检查 fail-closed,capsule 策略逻辑也要对齐”的分层思想一致:每一层知道自己是否是最终防线,策略层若想做最终裁决就必须用显式的Deny,而不能依赖异常。同时matcher_holds(crates/aos-mcp-broker/src/policy.rs)保证“缺失的参数永远不会意外满足一条 deny 规则”,即不可信输入无法通过缺省路径绕过策略。
围绕现有资源边界做设计
第四节列出了当前运行时的作者相关限制。指南提醒:限制是随运行时版本演进的,依赖某个精确数值前应先检查所固定的运行时源码(inspect the pinned source)。当前作者相关的默认限制包括:
- 有界(bounded)的文件系统调用大小与目录列举;
- 动态订阅数量上限;
- 有界的并发主机进程数;
- WASM 执行时间/epoch 中断;
- 有界的工具描述收集(bounded tool-description collection)。
然后给出七条“假设一切外部资源都有限”的设计规则:
- 大数据流式化或分页(stream or page);
- 限制消息与 trace 的保留量;
- 请求/响应流程加超时;
- 重试使用 compare-and-swap 或幂等键(idempotency keys);
- 对平台事件去重;
- 用背压(backpressure)显式表达容量,而不是派生无界工作;
- 长生命周期工作在安全边界处做检查点(checkpoint)。
指南还特别指出:uplink与持久进程(persistent processes)会放宽常规的“生命周期随调用结束”假设,因此需要更强的关停(shutdown)、所有权(ownership)与恢复(recovery)设计。这与 capsules/capsule-forge/src/lib.rs 中suggest_capabilities对这些能力的描述互相印证:host_process需要逐个列出可执行文件白名单,allow_persistent = true是“叠加在可执行文件白名单之上的显式布尔子授权”,uplink = true则“仅在真实的协议边缘(real protocol edge)才应使用”。换言之,放宽生命周期的能力在清单层面就要求作者做出更强的显式承诺。
Principal 隔离:状态、路径、环境与密钥按调用选择
第五节的规则:
- 状态、home 路径、环境变量、密钥都按调用(per invocation)选择;
- 绝不把 principal 专属的值缓存在全局;
- 属于 principal 作用域 KV 的数据,不要放进可变全局状态;
- 跨 principal 服务必须把共享/运维作用域(shared/operator scope)显式化,并且把授权与查找(lookup)分开;
- 调用方在 JSON 字段里声称自己是另一个 principal,不产生任何以该 principal 行事的权限。
仓库中对“运行时按 capsule + principal 序列化执行”的说明见 capsules/capsule-forge/src/guides/ipc.md:“调用身份来自内核盖戳的信封(kernel-stamped envelope);运行时在必要时按 capsule 与 principal 序列化执行,避免可变状态成为跨 principal 竞态。不要添加破坏这种隔离的全局缓存。动态接收超时返回Ok+ 空集合,应判空而不是匹配错误字符串;敏感动作前对每条消息校验来源与 principal。” 这与 security 章节“不要缓存 principal 专属值到全局”的告诫完全咬合:静态缓存一旦混入 principal 专属数据,就是隔离漏洞。
供应链与安装
第六节覆盖从构建到安装的完整信任链:
- 可安装的
.capsule归档必须通过官方构建器构建; - 拒绝不安全的归档路径、符号链接、重复的便携名、以及未声明的资产;
- 保持“源码 → 产物 → 校验和/出处证明(checksum/provenance)→ 已安装字节 → 运行身份”全程可追溯;
- 不重打标签(retag)或静默替换已发布的发布字节;
- 把主机进程与 MCP 服务器视为显式的沙箱出口(explicit sandbox exits);
- 审查生命周期钩子(lifecycle hooks),因为它们运行在安装或升级期间。
关于钩子的具体面:从 capsules/capsule-forge/src/guides/capsule.md 的 SDK 注解一览可以看到#[astrid::install](安装生命周期钩子)与#[astrid::upgrade](接收前一版本的升级钩子)等入口。这些钩子在安装/升级窗口内执行,属于指南所说的“运行时机特殊、必须被单独审查”的代码面。审查时至少应确认:钩子逻辑与正文工具逻辑同等对待(同样的输入校验、fail-closed 语义),升级钩子能处理“升级进行到一半崩溃”后的残留状态——这正是下文对抗式评审清单中的问题之一。
评估强度与后果成正比
第七节的核心观点:不同风险等级的 capsule 需要不同强度的证明——一个本地格式化 Skill、一个只读连接器、一个身份管理员、一个发消息的平台 worker,其评估深度应当不同。
至少应评估:
- 代表性用例上的功能成功;
- 非法、恶意与被拒绝(denied)的输入;
- 权限范围与“负能力”测试(negative capability tests:断言没有的东西确实不能做);
- principal 隔离;
- 重启、重试、重复、超时行为;
- 从受支持的前一状态做升级;
- 对真实 harness 与留出任务(held-out tasks)的影响;
- 日志/trace 无密钥泄漏。
对于 meta-harness(元框架自动搜索式扩展)场景,指南要求保留基线、候选源码、任务分布、指标、成本与原始 trace;并且明确禁止“在留出评估集上优化”或“凭单个任务的轶事宣称泛化改进”。这与仓库中 meta-harness 指南的评估纪律一致,其边界声明(能力仍是操作边界、生成代码不能自我提权)可以在同目录的 capsules/capsule-forge/src/guides/meta-harness.md 与 capsules/capsule-forge/src/guides/authority.md 中继续核对——[capsules/capsule-forge/src/lib.rs](https://link.gitcode.com/i/f5331b3e50997d84c63f2e23040508df)的测试authority_manual_separates_construction_from_activation就断言 authority 章节必须包含“Generated code cannot self-promote”(生成代码不能自我提权)。
对抗式评审问题清单
最后一节是一组可直接照用的评审问题(adversarial review questions),建议作为 PR/发布前 checklist:
- 如果模型提供了穿越路径(traversal path)或开放代理 URL(open-proxy URL),会发生什么?
- 载荷能否伪造(spoof)一个 principal 或 provider?
- 某个错误会不会“意外地让策略链继续执行”?(对应 fail-open 陷阱)
- 重试会不会复制外部副作用(duplicate an external effect)?
- 一个 principal 的配置会不会通过静态缓存泄漏给另一个?
- 宽泛的通配符能否被收窄?
- 主机进程能否逃逸出预期的可执行文件/参数边界?
- 升级进行到一半崩溃时,什么状态会存活下来?
- 生成的 Skill 或插件是否指示了操作系统(OS)并未授予的动作?
- 每一条“完成声明”(completion claim)是否都被“实际被测试的那个工件”所支撑?
指南以一句结论收尾:“安全是真实的门控(real gates)与良好设计的边缘(well-designed edges)的组合,而不是提示词里的一句声明(not a claim in a prompt)。”
小结:把安全章节落成可验证的工程动作
把本文各节压缩成一份落地检查表:
| 主题 | 核心动作 | 仓库佐证 |
|---|---|---|
| 信任边界 | 输入默认敌对,论证只落在六类可执行边界上 | manifest.md 声明清单为不可信输入 |
| 边缘校验 | 拒绝空/畸形/超大/穿越值;argv 不拼 shell;错误不回显输入 | lib.rs#L186-L197validate_name |
| Fail-closed | 策略层阻断必须显式Deny,Err只记日志并继续 | ipc.md#L98-L127;policy.rs#L142-L178 |
| 资源边界 | 流式化、幂等、超时、背压、检查点 | security.md“Current resource boundaries”一节 |
| Principal 隔离 | 按调用选择状态/环境/密钥;禁止 principal 专属全局缓存 | ipc.md#L129-L138 |
| 供应链 | 官方构建器、可追溯、钩子需审查 | Capsule.toml 最小能力示例 |
| 评估与评审 | 按后果分层评估;逐项过对抗式清单 | security.md 最后两节 |
最后强调适用前提:以上限制数值与能力字段(如uplink、allow_persistent、allow_prompt_injection)均为当前仓库版本的描述,指南本身也提醒“依赖精确数值前先检查所固定的运行时源码”。在把该清单用于自己的 capsule 时,应以你所固定的运行时版本对应的 WIT 契约与内核实现为准。
【免费下载链接】aos-ce
AOS Community Edition: the open agent operating system.
相关推荐
OpenMed 多语言摄入威胁模型:字典、编码与区域设置的 Fail-Closed 安全边界设计
OpenMed 多语言摄入威胁模型:字典、编码与区域设置的 Fail Closed 安全边界设计 导读 本文基于 OpenMed 仓库的 threat mode
人工智能NLP医疗健康数据脱敏本地部署大模型AI 应用MCP 服务联邦学习GetQzonehistory 教程:QQ空间说说、转发、留言备份到 Excel 的完整指南
GetQzonehistory 教程:QQ空间说说、转发、留言备份到 Excel 的完整指南 GetQzonehistory 是一个用 Python 编写的 Q
网页爬虫数据分析IronClaw 内核权威边界(Authority Perimeter):九阶段权限管线、密封见证与逐阶段 Fail-Closed 安全设计解析
IronClaw 内核权威边界(Authority Perimeter):九阶段权限管线、密封见证与逐阶段 Fail Closed 安全设计解析 本文以 cra
人工智能AI 应用交互助手AI Agent
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考