当你允许第三方 Skill 在你的 Agent 中运行时,需要做哪些安全隔离?
面试官:“如果允许第三方开发者在你的 Agent 平台上提交并运行 Skill,你需要做哪些安全隔离?”
候选人:
“第三方 Skill 运行的安全隔离,本质上是回答一个问题:怎么让一段不受信任的代码,在我们的系统里安全地跑起来,不窃取数据、不破坏环境、不滥用资源。 我的设计原则是:默认完全隔离,逐层声明授权,最小权限运行。 我把它拆成五道防线,从外层到内层逐步收紧。
第一道防线:代码打包与静态扫描
Skill 提交到市场后,不能直接以源代码或自由格式上传,必须遵循标准化打包规范。比如统一的 .skill 包格式,包含元信息、编译后的字节码、资源文件等。
提交后自动触发静态安全扫描流水线:
-
依赖漏洞扫描:检查 Skill 引用的第三方库是否存在已知 CVE 漏洞。
-
敏感 API 调用检测:扫描字节码中是否调用了危险方法(如
Runtime.exec()、File.delete()、反射、反序列化),如果有且未在权限声明中说明,直接拒绝。 -
代码风格与恶意模式匹配:检测是否包含混淆代码、加密字符串、动态加载等可疑模式。
这一步是把明显的恶意代码挡在门外,像机场安检的 X 光机,行李先过一遍,违禁品直接拦截。
第二道防线:权限声明与审核
通过静态扫描后,Skill 还不能直接运行。它在元信息里必须显式声明所需的最小权限集合,比如:
{
"permissions": {
"network": {
"allowed": true,
"domains": ["api.weather.com"],
"protocols": ["HTTPS"]
},
"file_system": {
"allowed": false
},
"exec": {
"allowed": false
},
"environment_variables": [],
"inter_skill_communication": {
"allowed": false
}
}
}
核心原则是:不声明即禁止。即使 Skill 内部尝试执行未声明的操作,运行时也会被拦截。
此外还要声明数据使用协议:这个 Skill 是否会把用户数据传出去?传到哪里?保留多久?这既保护了用户隐私,也方便合规审计。
对于高风险权限(如网络出口、数据库访问),平台可以要求人工审核,或者限制非认证开发者不能申请。
第三道防线:沙箱运行时隔离
静态分析和声明都是“纸面上的安全”,真正执行时,Skill 必须跑在隔离沙箱里。沙箱确保即使 Skill 代码有恶意逻辑,也无法突破边界。
我常用的三层沙箱方案:
无论哪种方案,沙箱的统一配置原则是:
-
网络隔离:默认断网,仅开放声明的域名白名单,通过
iptables或网络命名空间控制。 -
文件系统隔离:只读挂载必要的运行时文件,Skill 写入的目录是临时分配且限容的,执行完自动清理。
-
系统调用过滤:用
seccomp限制可用的系统调用,比如禁止fork、mount、reboot。 -
禁止提权:容器内用户非 root,去除所有
CAP能力。
第四道防线:能力网关与运行时拦截
Skill 在沙箱内也不能直接调用外部 API 或访问数据库,所有外部能力必须通过 Agent 框架提供的能力网关。
网关的工作方式:
-
Skill 调用一个外部服务时,不是直接发 HTTP 请求,而是调用网关暴露的受限接口。
-
网关收到请求后,检查该 Skill 的权限声明:是否允许访问这个域名?频率是否超限?参数是否合法?
-
检查通过才转发,否则拒绝并告警。
这一步把 Skill 对外部世界的所有交互都变成了受审的请求。网关还可以做数据脱敏:如果 Skill 请求了用户手机号字段,网关可以替换为脱敏后的值,只给 Skill 必要的业务数据。
第五道防线:资源配额与运行时监控
即便 Skill 行为合规,也可能因为代码缺陷(死循环、内存泄漏)耗尽资源。因此必须设定严格的资源配额:
-
CPU 时间限制:单次执行最长 10 秒,超时强制 kill。
-
内存限制:最大 128MB,超出则 OOM 并回收沙箱。
-
网络速率限制:每秒最多 10 次外部请求,防止被当成代理攻击。
-
磁盘 IO 限制:临时存储最多 50MB,超出抛异常。
所有 Skill 的执行行为都记录审计日志:谁在什么时间、调用哪个 Skill、访问了哪些资源、返回了什么状态码。异常行为(如频繁超时、越权尝试)触发实时告警。