Heurion Research

为什么 Agent 插件不是安全边界:从 Advisory Hook 到内核级 Enforced Runtime 的架构演进

当 Agent 与它的监督器运行在同一个宿主权限域时,任何 Hook 与提示词都只是“礼貌的建议”。本文详解 Aegis OS 如何通过父进程内核启动器(aegis-os run)、单文件只读配置挂载、只读 .git 穿透与两层网络网关,将安全边界下沉至操作系统内核。

01. 诚实的威胁建模:为什么 Agent 插件与 Hook 只是“建议”而非安全边界?

在构建智能体基础设施时,最危险的工程幻觉莫过于把“工作流编排插件”当成“操作系统安全边界”。今天主流的终端与 IDE 智能体(如 Claude Code、OpenCode、Codex CLI、Antigravity AGY、Hermes 等)普遍提供了三类扩展接口:系统提示词规则(CLAUDE.md / AGENTS.md)、工具拦截钩子(PreToolUse Hook / Plugin)以及 Model Context Protocol(MCP)工具服务器。

当智能体处于良性协作状态时,基于插件的治理非常高效:Hook 可以把宿主机上的原生 Read、Edit、Bash 自动重写并透明路由到 Aegis OS 的写时复制(CoW)影子工作区中。然而,只要我们从操作系统内核的视角审视进程树,就会发现一个不可回避的事实:在插件模式下,Agent 主进程本身直接运行在宿主机的用户权限域中,拥有与人类开发者完全相同的 UID、$HOME 目录可见性与系统调用能力。

安全边界第一性原理(Kernel Boundary Axiom)

任何运行在被监管进程同一权限域内、或依赖被监管进程主动配合调用的拦截器,都不是安全边界。只要 Agent 自身未被置于内核沙箱(Mount / PID / Network Namespace 或 Seatbelt / microVM)之内,Hook 与 MCP 提供的就只是建议级防护(Advisory Governance),而非强制级隔离(Enforced Isolation)。

我们在对主流 CLI 与桌面 Agent 进行端到端审计时,梳理出仅靠 Hook + MCP 无法根除的六大结构性绕过面:

绕过向量(Bypass Vector) 触发机制与真实客户端表现 仅靠 Hook / 插件为何无法根治
1. 原生工具覆盖盲区 如 NotebookEdit、内置 LSP 重构、第三方 MCP Server(如直接挂载宿主的 filesystem MCP)未列入重写规则 Hook 采用黑名单枚举工具名,一旦客户端升级新增工具或项目注入 .mcp.json,立即穿透至宿主机
2. 客户端根本不支持工具级 Hook 例如 Codex CLI 支持 MCP Server 与自带沙箱,但当前版本并未向外部暴露 PreToolUse 拦截钩子 只能依靠 AGENTS.md 软提示词引导模型调用 MCP 工具,对恶意提示词注入(Prompt Injection)零硬性约束
3. 共享守护进程状态逃逸 OpenCode TUI 若通过 --attach 连接到已运行的后台 Server,插件的加载与否完全取决于守护进程启动时的环境 外层 CLI 包装器无法改变已存活守护进程的命名空间与插件表,导致工具调用脱离当前会话沙箱
4. 配置文件自篡改与项目级覆盖 Agent 或仓库内的构建脚本修改 ~/.claude/settings.json、.claude/settings.local.json 或 opencode.json 当 Agent 进程对自身配置目录拥有写权限时,可通过清空 Hook 配置在下一轮会话中彻底摘除监管
5. 只读命令与构建脚本的宿主副作用 放行看似无害的 git status、cargo test 或 npm test 在宿主机执行 build.rs、postinstall 或 .git/config 中的 core.fsmonitor 可在宿主侧执行任意代码并窃取 ~/.ssh
6. 本机 Loopback 越权自批 沙箱内或本机脚本直接访问 127.0.0.1 上的审批守护进程 API 尝试自动批准 Escalation Ticket 若 Broker 缺乏按角色隔离的 Session Token(Agent Token vs Human Admin Token),同 UID 进程可伪造人类审批

02. 三档强制边界(Advisory / Enforced / Isolated):把生产力协作与强制隔离解耦

承认插件模式的局限性,并不意味着要废弃插件;恰恰相反,工程上最糟糕的做法是“用极端的默认拒绝破坏 95% 的日常开发体验,或者用模糊的宣传掩盖安全边界”。为此,Aegis OS 将运行时明确划分为三档可验证的强制等级(Enforcement Tiers),并在 aegis-os status 与 aegis-os doctor 中实时向用户诚实展示当前所处的安全等级:

TIER 1 · ADVISORY (PLUGIN) 插件与 Hook 协同模式 • 入口: 直接运行 claude / agy • 机制: PreToolUse + MCP 路由 • 收益: CoW 影子写 + 多 Agent 锁 • 宿主隔离: 仅 MCP 内子进程沙箱 定位:防误操作生产力护栏 防意外覆写与并发冲突;不承诺抵御 恶意 Prompt Injection 绕过原生工具 TIER 2 · ENFORCED (KERNEL) 父进程内核沙箱模式(核心) • 入口: aegis-os run -- <agent> • 机制: bwrap + Landlock / Seatbelt • 视图: 路径重映射 CoW + .git 只读 • 网络: --unshare-net + Unix 代理桥 定位:OS 内核强制安全边界 即使 Hook 失效或模型被劫持,整个 Agent 进程树也无法触碰宿主与凭据 TIER 3 · ISOLATED (MICROVM) 独立内核与远程沙箱模式 • 入口: aegis-os run --isolated • 机制: libkrun MicroVM / Cloud VM • 视图: virtiofs 仅挂载影子工作区 • 凭据: 零本地挂载,网关代填密钥 定位:不受信任代码与高敏合规 硬件虚拟化隔离宿主机内核,适用于 医院内网、金融合规与无人值守 CI 统一不变量:未降级静默放行(Fail-Closed) · 宿主写入必经 Diff 审批 · Agent Token 严禁调用审批接口
图 1:Aegis OS 三档强制边界(Advisory / Enforced / Isolated)。明确区分“建议级生产力护栏”与“内核强制安全边界”。

03. 控制权反转:aegis-os run 父进程启动器、只读 .git 穿透与状态目录分层挂载

要从 Advisory 跃迁到 Enforced,核心架构动作只有一句话:反转父子进程关系——不再让 Agent 在宿主机里按需调用 Aegis,而是由 aegis-os run -- <agent> 作为父进程先构建受限内核命名空间,再在沙箱内部 execve 启动 Agent 本身。

然而,将一个复杂的现代 CLI Agent(如 Claude Code 或 OpenCode)整个放进 Linux bubblewrap (bwrap) + Landlock + seccomp 或 macOS Seatbelt 沙箱中,如果设计粗糙,立刻就会遇到三个棘手的工程死锁:(1)NixOS / Homebrew / 动态链接器路径缺失导致二进制无法启动;(2)Agent 在沙箱内运行 git status / git diff 报错或触发宿主机恶意 Git Hook;(3)Agent 无法写入自己的会话历史(~/.claude/projects)或被允许篡改自己的安全配置(~/.claude/settings.json)。

Aegis Enforced Runtime 通过三项精巧的系统设计彻底解决了上述矛盾:

3.1 保留 --ro-bind / / 的发行版兼容遮蔽 + 路径重映射(Path Remapping)

如果放弃根目录只读绑定而尝试手工枚举 /usr、/lib,在 NixOS(/nix/store)、Linuxbrew(/home/linuxbrew/.linuxbrew)、Snap 或自定义 CA 证书路径下极易触发 ENOENT 与 TLS 握手失败。因此,我们在 Linux 下保留 --ro-bind / / 保证 100% 发行版二进制兼容,紧接着使用 --tmpfs 彻底遮蔽 /home、/root、/run、/var、/tmp、/mnt、/media 与 /etc 敏感凭据文件,最后按最小白名单把 CoW 影子工作区原路径挂载到 /home/user/project,而把宿主机真实项目只读挂载到 /aegis/host/project。这样,Agent 无论使用原生工具还是直接 python -c "open('src/main.rs', 'w')",它以为自己在改宿主路径,实际上全部落入了隔离的 CoW 影子层!

3.2 只读 .git 对象库穿透与 GIT_INDEX_FILE 会话索引分离

开发者和 Agent 高度依赖 git status、git diff、git log 与状态栏分支显示。如果为了省事在影子目录拷贝中排除 .git,所有 Git 命令都会崩溃;但如果把整个 .git 拷贝一份,大型仓库会增加数百 MB 的启动开销;如果直接把宿主 .git 可写暴露给沙箱,Agent 写入 .git/hooks/pre-commit 或 .git/config 的 core.fsmonitor 就会在宿主机上实现远程代码执行(RCE)。

Aegis OS 的解法是“只读对象库 + 独立可写暂存区索引 + 安全 Git Shim”:

# 1. 宿主 .git 整个只读挂载到沙箱工作区(objects / refs / HEAD 零拷贝可见,hooks / config 不可写)
bwrap ... --ro-bind /aegis/host/project/.git /home/jz/project/.git

# 2. 会话启动时复制单文件 .git/index 到沙箱私有目录,并通过环境变量重定向写入
cp /aegis/host/project/.git/index ~/.aegis/sessions/$SESSION_ID/git-index
export GIT_INDEX_FILE="$HOME/.aegis-git-index"
export GIT_OPTIONAL_LOCKS=0
export GIT_CONFIG_NOSYSTEM=1
export GIT_CONFIG_GLOBAL=/dev/null

# 3. 内置 Git 安全 Shim 强制注入禁用外部执行器参数,拦截 commit/push 引导至 aos commit
git -c core.fsmonitor=false -c core.hooksPath=/dev/null status --no-ext-diff

如此一来,git status 与 git diff 在 10 万文件级仓库中依然瞬时响应且需要刷新 stat 缓存时只写沙箱私有的 .aegis-git-index,宿主机 .git/index 的 mtime 纹丝不动,且任何恶意的仓库级 Git Hook 均无法被安装或触发。

3.3 Agent 状态目录的“单文件只读锁(Config Lock)”

CLI Agent 在运行期必须写入会话日志、Todo 列表与 OAuth 刷新令牌(如 ~/.claude/projects/*.jsonl、~/.codex/sessions、~/.local/share/opencode 的 SQLite),但绝不能允许它修改 ~/.claude/settings.json、~/.gemini/config/hooks.json 或 ~/.codex/config.toml。我们利用 Linux Mount Namespace 的顺序覆盖特性:先按需可写挂载状态子目录(projects/、todos/),再在顶层对敏感配置文件执行单文件 --ro-bind 只读覆盖——既保障了客户端完整有状态体验,又从内核层封死了“Agent 篡改自身配置摘除监管”的逃逸路径。

HOST BROKER · aegis-os run 宿主可信监管层(沙箱外) • Session Token (Agent != Human) • Cedar Effect 策略与租约引擎 • SHA-256 证据锁定审批队列 • CoW backend: APFS / OverlayFS 真实宿主仓库 (/aegis/host) • 仅在 workspace_commit 审批后 通过三路 LCS 原子落地 KERNEL SANDBOX NAMESPACE 受控视图(Agent 进程树) • cwd 映射至 CoW Shadow (rw) • .git 对象库只读 + 独立 index • settings.json / hooks.json (ro) • ~/.ssh, ~/.aws, /etc/shadow 遮蔽 OpenCode 强制 --standalone • 禁止附着沙箱外共享守护进程 • seccomp 拦截 mount/ptrace/bpf DUAL-MODE EGRESS PROXY --unshare-net + Unix 桥接 1. CONNECT 隧道 (net.connect) 域名/端口白名单 · 零流式延迟 2. Base URL 反向代理 (net.request) L7 Method 审计 · 密钥边界代填 3. Opt-in MITM(按需显式开启) 仅针对声明域名启用会话级 CA 绝不默认破坏 TLS Pinning
图 2:aegis-os run 父进程沙箱的内核挂载拓扑与两层网络出站代理架构。

04. Effect 驱动策略与两层出站网关:区分 CONNECT 隧道与 Base URL 反向代理

传统安全工具常犯的另一个错误是“对命令字符串做正则匹配审批”。但在真实工程中,“命令(Command)”不是安全原语,“效果(Effect)”才是——cargo test 会在影子工作区内读写数百个文件并编译执行测试二进制,只要它被严格限制在 CoW 影子和只读工具链内,就不应该弹窗打扰用户;相反,一次看似简单的文件写入如果触碰了 .github/workflows/release.yml 或 build.rs,在提交回宿主机时就属于高危的持久化投毒(Commit-Time Poisoning)。

因此,Aegis OS 将所有底层动作统一抽象为 (EffectKind, ResourceScope, Reversibility) 三元组:影子区内的可逆读写(Reversible)默认静默放行并自动建立快照;只有跨越边界的不可逆动作(workspace.commit、workspace.commit_sensitive、访问项目外 $HOME 路径或未授权外网连接)才进入 Cedar 策略引擎与人类租约审批。

在网络出站(Egress)治理上,我们也摒弃了“把 HTTPS CONNECT 代理吹嘘成全能 L7 DLP”的不诚实做法。标准 HTTPS CONNECT 是端到端 TLS 加密隧道,代理只能看到 host:port,根本看不到 HTTP Method(GET/POST)、URL Path 或 Request Body。因此,Aegis OS 明确划分了两层默认出站网关 + 一层可选扩展:

  • L4 CONNECT 隧道模式(默认覆盖包管理器与通用 HTTPS):策略动作对应 net.connect(如 net:registry.npmjs.org:443)。仅执行零延迟的域名/端口白名单与流量字节统计,绝不伪造 Method 审计,也不破坏任何客户端的 TLS 证书固定(Certificate Pinning)。
  • L7 Base URL 反向代理模式(推荐用于大模型与核心 SaaS API):由 Launcher 自动注入 ANTHROPIC_BASE_URL / OPENAI_BASE_URL 指向沙箱本地网关。客户端到网关走本地环回 HTTP,网关再以 TLS 连接真实上游并完成边界密钥代填(Agent 进程内永远拿不到真实的 ANTHROPIC_API_KEY 明文)、HTTP Method/Path 审计(net.request)与请求体敏感信息(PHI / 密钥)DLP 拦截,同时对 SSE 流式响应保持零首 Token 缓冲延迟。
  • Opt-in MITM 模式(仅限企业显式声明域名):仅对列入 mitm_domains 的目标签发会话级 CA 并注入信任链,若遇证书 Pinning 失败则显式告警降级,绝不静默假装存在 DLP。

05. 跨领域通用事务流水线与无破坏 TUI 审批(DECSTBM / OSC / 离线租约)

今天知识工作者的 Agent 早已走出纯代码仓库(Code),广泛进入学术论文与标书(Documents)、临床与生物统计数据集(Data)、设计图与医学影像(Binary)以及在线业务系统(AppState)。如果一套运行时只会保护 git diff,在面对非代码场景时就会退化回裸奔状态。

Aegis Enforced Runtime 将底层的 shadow → verify → approve → land 提交流水线抽象为可插拔的领域配置(DomainProfile):

  • Code & Documents(代码与 Markdown/LaTeX 手稿):采用四级 LCS 三路自动合并;预检门(verify_cmd)在沙箱内执行 cargo test 或 latexmk -pdf + 死链检查;Office 文档(.docx / .pptx)在 Phase 5 对接 Heurion 双表面 CRDT 的块级锁与 patchParagraph 字节级补丁。
  • Binary(二进制图表、PDF、TIFF 影像):天然不可按行合并。强制执行 coord_claim 排他文件锁 + 影子创建时的基线 SHA-256 哈希锚定(Baseline Hash Guard),任何覆盖宿主二进制资产的提交必须通过 overwrite_binaries 单次审批并附带新旧哈希对比证据。
  • Data & Org CAS(科研数据集与跨智能体产物总线):上游清洗智能体必须通过沙箱内的 Schema 校验与 scanPhi --strict 隐私扫描后,将产物发布至不可变的 SHA-256 内容寻址总线(org_artifact_publish),从机制上杜绝下游智能体读取未完成的半成品文件。
工程细节决定成败:为什么审批绝不能直接往活跃 TUI 的 stderr 写文本?

当 Claude Code、OpenCode 或 Codex 正在全屏 Alternate Screen / Raw Mode 下渲染高帧率 TUI 时,如果父进程沙箱直接往同一个 PTY 的 stderr 打印审批提示或争抢 [a]pprove / [d]eny 键盘输入,会瞬间导致终端花屏与输入死锁。因此,Aegis OS 在检测到全屏 TUI 活跃时,严禁向主屏幕直接写入审批字符,而是通过桌面通知、终端 OSC 0 标题栏闪烁提示(⏳ Aegis: 1 approval pending)、另一终端的 aegis-os approve CLI 或带 SHA-256 Diff 锁定的本地 Web 审批台完成场外确认;在纯 SSH 场景下则可选使用 DECSTBM 划定顶部 1 行独立状态栏。只有尊重每一个系统工程细节,内核级安全边界才能真正成为开发者每天愿意默认开启的基础设施。

读者评论

0 条留言

暂无留言,欢迎在下方分享你的见解或技术讨论。