安全机制
wescode 的安全架构——治理管道、exec 安全、密钥管理与配额控制。
CellGovernance 三步管道
每个工具调用经过三步安全检查:
工具调用请求
→ ① Hardline(灾难命令拦截)
→ ② Sandbox(数据边界检查)
→ ③ Zone(效果分类 + Mode 决策)
→ 允许 / 拒绝
三步管道特性
| 步骤 | 职责 | 可覆盖 |
|---|---|---|
| Hardline | 灾难命令拦截(18 条正则) | ❌ 永不可覆盖 |
| Sandbox | 数据边界(DenyPaths + 网络) | 按 CellSpec 配置 |
| Zone | 效果分类(Green/Yellow/Red) | 按 GovernMode 配置 |
治理链不产生 HITL——HITL 仅用于 Agent 主动交互(ask_user / browser_wait_for_user / CycleDetector)。
GovernMode 预设
| 预设 | GovernMode | Yellow Zone | 典型用途 |
|---|---|---|---|
| 编程模式 | open | Allow + Audit | 日常编程(wescode 默认) |
| 助手模式 | open | Allow + Audit | 通用助手 |
| 锁定模式 | locked | Deny | 金融合规/展示 |
| 基准模式 | open | Allow | BenchMode 评测 |
Compliance 预设映射
| Compliance | GovernMode | NetworkPolicy | 适用 |
|---|---|---|---|
StandardPreset() | open | allow | wescode 默认 |
RegulatedPreset() | locked | internal_only | 金融/PII |
ReadonlyPreset() | locked | deny | 展示/demo |
wescode 默认使用 StandardPreset()(open + allow)。
Hardline 灾难命令
18 条正则匹配不可覆盖的灾难命令:
rm -rf / # 删除根目录
:(){ :|:& };: # Fork bomb
shutdown / reboot / halt # 系统关机
kill -9 1 # 杀死 init
mkfs / dd if=/dev/zero # 磁盘格式化
... 等 18 条
检测范围(INV-GOV-01)
Hardline 不限于 exec 工具——对所有工具检查 command/cmd/script/shell JSON 字段:
// MCP 代理工具也会被检查
{
"tool": "my_mcp_tool",
"command": "rm -rf /" // ← Hardline 拦截
}
Sandbox
DenyPaths
禁止工具访问的路径列表:
spec := wesgine.CellSpec{
DenyPaths: []string{
filepath.Join(dirs.DataDir(), "hypervisor.db"),
dirs.ConfigFile(),
},
}
NetworkPolicy(INV-GOV-02)
| 策略 | 行为 |
|---|---|
allow | 允许网络访问(wescode 默认) |
internal_only | 只允许内网 |
deny | 禁止所有网络 |
在 deny 或 internal_only 模式下,Sandbox 检测 exec 命令中的网络工具:
检测列表:curl / wget / nc / ncat / netcat / ssh / scp / sftp / rsync
检测方式:按命令位置(行首 / 分隔符后 / 子 shell 中)
→ "grep -r curl ." → 不拦截(参数位置的 curl)
→ "curl https://..." → 拦截(命令位置的 curl)
exec 安全
KillProcessGroup(INV-EXEC-11)
前台 exec 超时后杀死整个进程组:
exec 超时 → ctx 结束
→ KillProcessGroup()(杀整个进程组)
→ 防止逃逸的 grandchild 存活
stdout 排空(INV-EXEC-12)
进程退出后最多等 5s 排空 stdout:
进程退出 → stdout 排空(最多 5s)
→ 超时 → 强制 CloseOutput()
→ 解除 scanner 阻塞(grandchild 持有管道写端场景)
proc.Command 单一原语(INV-EXEC-PROC-01)
一个原语生成子进程:
// 正确:使用 proc.Command
cmd := proc.Command(ctx, "go", "build", "./...")
// 自动设置:Setpgid + Cancel + WaitDelay
// 禁止:裸 exec.Command / exec.CommandContext
cmd := exec.Command("go", "build", "./...") // ❌ 缺少进程组管理
管道排空(INV-EXEC-DRAIN-01)
exec 输出读取必须无条件消费管道直到 EOF:
禁止 bufio.Scanner(1MB max-token 限制)
→ 大输出时提前退出 → 管道无人消费 → 子进程阻塞 → 死锁
使用 ReadSlice 循环(64KB 块)+ cappedWriter 限内存
SanitizeEnv
exec 子进程与引擎同 UID,凭据隔离靠 SanitizeEnv 两层:
| 层 | 机制 | 说明 |
|---|---|---|
| 静态模式 | INV-SEC-04 | 预定义的敏感变量模式表 |
| 动态登记 | INV-SEC-03 | SecretRef{source:env} 的变量名 |
// 子进程环境变量中清除:
// - OPENAI_API_KEY, ANTHROPIC_API_KEY 等(静态模式)
// - 用户配置的 SecretRef env 变量名(动态登记)
CellQuotas
per-Cell 的资源配额限制:
配额维度
| 维度 | 配额项 |
|---|---|
| 计算 | MaxConcurrentRuns / TokensPerMinute / TokensPerDay |
| 存储 | 磁盘配额 |
| 外设 | MaxIMChannels / MaxMCPServers / MaxCronJobs / MaxEmailAccounts / MaxSkillsInstalled |
| Exec | 执行限制 |
超限行为
| 维度 | 超限行为 |
|---|---|
| 计算 | 429(稍后重试) |
| 存储 | GC / 拒绝写入 |
| 外设 | 拒绝安装 |
SecretRef 密钥管理
三种来源
| 来源 | 说明 | 加密 |
|---|---|---|
inline | 直接存储(AES-256-GCM 封套) | ✅ |
env | 环境变量引用 | ❌(不落盘) |
live | 运行时动态获取 | ❌(不落盘) |
inline 加密(AES-256-GCM)
用户输入明文 API Key
→ config.MapSecretValues(spec, box.Seal)
→ AES-256-GCM 加密
→ 密文存入 hypervisor.db
→ 密钥文件: {DataDir}/secrets/spec.key (0600, 目录 0700)
出网脱敏(INV-SEC-02)
只有一个执行点 config.RedactSecrets:
// 所有出网的 spec 都经过 RedactSecrets
// → API Key → "***"
// → 密码 → "***"
delegate_task 安全
delegate_task 归类为 ZoneRed(INV-GOV-03)——最高安全级别:
ZoneRed 行为:
→ 条件允许(需要审计)
→ 子 Agent 启动记录在 Evidence 中
→ Actor 必须从父 Run 继承(不可伪造)
最佳实践
- 使用默认 StandardPreset:wescode 开发场景足够安全
- 配置 DenyPaths:保护敏感配置文件
- 不要修改 Hardline:18 条灾难命令不可也不应覆盖
- BYOK 使用 inline:AES-256-GCM 加密保护 API Key
- 理解 exec 安全:proc.Command 自动处理进程组管理