Skip to content

11. 权限、安全与可扩展性

本章定位

大模型拥有工具调用能力后,其实就拥有了执行代码、访问文件、调用外部网络 API 的潜在行为。若没有必要的约束和安全防御,可能会由于恶意的提示词注入(Prompt Injection)触发未预期的系统操作。

作为一个教学演示 Demo,L1 阶段只建立起最基础的“显式白名单约束”与“人工确认属性预留”,不包含完整的生产级沙箱和动态鉴权隔离。

本章旨在向大家展示如何在编写 Harness 架构早期阶段,就融入防御性设计的意识。


工具调用面临的安全课题

当我们在代码里允许 LLM 识别意图并运行函数时,我们需要防范:

  • 恶意注入指令:用户通过输入精心设计的攻击性提示词,劫持大模型的输出,强迫大模型生成非预期的工具调用(例如尝试写文件)。
  • 非预期的越权操作:模型逻辑判断失误,自动在后台触发了具有危险副作用的工具(例如删除文件)。

L1 中的最小防御演示

hachimi 代码中,我们使用了这几条最小的安全底线设计:

1. 显式白名单注册

我们不使用任何动态类反射或扫描文件自动注册的设计。大模型只能看到我们在启动入口中,通过 tools.registerskills.register 显式写入 Map 缓存的工具。没有被显式关联进来的代码,大模型在 Prompt 提示词中无法知晓,自然也无法触发执行。

2. 审批流拦截接口属性定义

我们在 packages/core/src/types/index.tsToolDefinition 中留下了如下属性定义:

ts
export interface ToolDefinition {
  name: string;
  description: string;
  parameters: Record<string, unknown>;
  execute: (args: Record<string, unknown>, ctx: ToolContext) => Promise<string>;
  
  /**
   * 1. 声明执行此工具所需的最低安全等级级别(预留)
   */
  requiredPermission?: PermissionLevel;
  
  /**
   * 2. 执行前是否需要人工输入进行审批确认
   */
  requiresApproval?: boolean;
}

export type PermissionLevel = "none" | "read" | "write" | "network" | "system" | "dangerous";

requiresApproval 设置为 true,控制层框架在循环中捕获该 tool_call 后,会将其挂起,提示用户确认是否放行,验证“默认不信任”的安全设计模式。


L2 安全演进计划

对于想要将 Agent 落地到真实生产环境的开发者,后续的进阶演进包括:

  • 沙箱隔离 (Sandboxing):将所有的脚本执行、文件读写、网页爬取工具等放入隔离的 WASM 环境或极轻量的 Docker 容器中执行,确保其没有直接访问宿主机资源的权限。
  • 动态审批通知流:与聊天终端联动,向用户发出审批卡片。
  • 输入 WAF 过滤:过滤用户输入,阻断常见注入载荷。

本章总结

本章我们:

  • 梳理了 Agent 工具调用中的注入和越权安全隐患。
  • 讲解了 PermissionLevelrequiresApproval 的接口设计。
  • 讨论了 L2 阶段沙箱化与安全加固的技术演化方向。