11. 权限、安全与可扩展性
本章定位
大模型拥有工具调用能力后,其实就拥有了执行代码、访问文件、调用外部网络 API 的潜在行为。若没有必要的约束和安全防御,可能会由于恶意的提示词注入(Prompt Injection)触发未预期的系统操作。
作为一个教学演示 Demo,L1 阶段只建立起最基础的“显式白名单约束”与“人工确认属性预留”,不包含完整的生产级沙箱和动态鉴权隔离。
本章旨在向大家展示如何在编写 Harness 架构早期阶段,就融入防御性设计的意识。
工具调用面临的安全课题
当我们在代码里允许 LLM 识别意图并运行函数时,我们需要防范:
- 恶意注入指令:用户通过输入精心设计的攻击性提示词,劫持大模型的输出,强迫大模型生成非预期的工具调用(例如尝试写文件)。
- 非预期的越权操作:模型逻辑判断失误,自动在后台触发了具有危险副作用的工具(例如删除文件)。
L1 中的最小防御演示
在 hachimi 代码中,我们使用了这几条最小的安全底线设计:
1. 显式白名单注册
我们不使用任何动态类反射或扫描文件自动注册的设计。大模型只能看到我们在启动入口中,通过 tools.register 和 skills.register 显式写入 Map 缓存的工具。没有被显式关联进来的代码,大模型在 Prompt 提示词中无法知晓,自然也无法触发执行。
2. 审批流拦截接口属性定义
我们在 packages/core/src/types/index.ts 的 ToolDefinition 中留下了如下属性定义:
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 工具调用中的注入和越权安全隐患。
- 讲解了
PermissionLevel与requiresApproval的接口设计。 - 讨论了 L2 阶段沙箱化与安全加固的技术演化方向。