安全加固
wesgine 提供多层安全机制:认证与授权(Token 体系)、密钥管理(SecretRef)、治理策略(Governance)、网络策略、审计日志和凭据泄漏扫描。
认证与授权
Token 体系
wesgine 使用两级 Token:
| Token 类型 | 用途 | 签发 | 作用域 |
|---|---|---|---|
| Admin Token | Hypervisor 管理 | hyp.Tokens().IssueAdminToken(ttl) | 全局管理 |
| Cell Token | Cell 业务操作 | cell.Tokens().IssueToken() | 单 Cell |
Admin Token
# 签发 Admin Token
curl -X POST -H "Authorization: Bearer <bootstrap-token>" \
http://localhost:9091/admin/tokens
# 吊销 Admin Token
curl -X DELETE -H "Authorization: Bearer <admin-token>" \
http://localhost:9091/admin/tokens/<token-id>
bootstrap token 在首次启动时生成,通过 stderr 输出(不走 logger,因为 journal 可能被转发出机器)。
Cell Token
Cell Token 支持 roles 控制粒度:
# 签发 Cell Token
curl -X POST -H "Authorization: Bearer <admin-token>" \
-H "Content-Type: application/json" \
-d '{"roles": ["cell:chat", "cell:read"]}' \
http://localhost:9091/cells/dept-legal/tokens
预定义作用域
| 作用域 | 说明 |
|---|---|
cell:read | 只读访问 |
cell:chat | 对话操作(Run/Chat/Session) |
cell:admin | Cell 管理操作 |
admin | Hypervisor 全局管理 |
Gateway 中间件认证链
请求到达 → path parse → cell exist → auth → temperature → quota → dispatch
认证失败返回 401;作用域不足返回 403。
Actor 与 Token 的关系
- 非 admin token:actor 从 token 提取,不可由请求覆盖
- admin token:
?actor=参数生效,用于管理视图 - 空 actor:admin 视图(全 Cell),非 admin 禁止
密钥管理(SecretRef)
三源模型
wesgine 统一使用 SecretRef 管理敏感信息:
| 源 | 说明 | 适用场景 |
|---|---|---|
inline | AES-256-GCM 封套加密存储 | 个人桌面部署 |
env | 从环境变量读取 | 服务端部署 |
live | 运行时通过 ProviderLiveKeyFn 获取 | 平台托管(JWT) |
inline 加密
providers:
- name: openai
api_key_ref:
source: inline
value: "sk-xxx..." # 存储时被 AES-256-GCM 加密
密文存储在 hypervisor.db,密钥在 {DataDir}/secrets/spec.key(权限 0600,目录 0700)。
env 引用
providers:
- name: openai
api_key_ref:
source: env
value: "OPENAI_API_KEY" # 从环境变量读取
live 动态获取
spec.ProviderLiveKeyFn = liveTokens.Key
// wes: → ValidAccessToken
// org: → IdentityAccessToken
降级态保护(INV-PERSIST-07)
spec.key 丢失时,解码失败的字段被清空——但不允许后续写入覆盖密文:
丢 spec.key → 字段解码失败,清空
→ Cell 继续运行(降级)
→ 任何写操作检查 degradedSecrets 台账
→ 被点名的字段为空 → 拒绝(409 ErrDegradedSecretOverwrite)
→ 除非本次写入带回非空值
治理策略(Governance)
三步管道
请求 → Hardline → Sandbox → Zone → 允许/拒绝
| 步骤 | 职责 | 可覆盖 |
|---|---|---|
| Hardline | 灾难命令拦截(18 条正则) | ❌ 不可覆盖 |
| Sandbox | 数据边界(DenyPaths / NetworkPolicy) | 部分可配 |
| Zone | 效果分类 + GovernMode 决策 | ✅ 可配 |
Hardline 命令拦截
18 条正则匹配灾难性命令,恒 Deny:
rm -rf /- fork bomb(
:(){ :|:& };:) shutdown/reboot/haltkill -9 1(杀 init)- 清磁盘(
dd if=/dev/zero) - 等
GovernMode
| Mode | Yellow Zone | 典型用途 |
|---|---|---|
open(默认) | Allow + Audit | 编程/助手/通用 |
locked | Deny | 金融合规/展示 |
NetworkPolicy
| 策略 | 说明 |
|---|---|
allow | 允许所有网络 |
internal_only | 仅内部网络 |
deny | 禁止网络 |
当 NetworkPolicy=deny 或 internal_only 时,exec 工具中的 curl/wget/nc/ssh 等网络命令被检测并拒绝(INV-GOV-02)。
Compliance 预设
一键装配完整治理策略:
// 金融合规
governance.RegulatedPreset()
// → GovernMode: locked
// → NetworkPolicy: internal_only
// → Redactor: 按场景配置
// 通用
governance.StandardPreset()
// → GovernMode: open
// → NetworkPolicy: allow
// 只读
governance.ReadonlyPreset()
// → GovernMode: locked
// → NetworkPolicy: deny
exec 安全模型
进程组管理
所有子进程通过 proc.Command 创建(INV-EXEC-PROC-01),确保:
- 建立进程组(
Setpgid) - Cancel 时
SIGKILL整个组 WaitDelay给Wait()封顶
环境变量隔离
SanitizeEnv 两层清洗:
- 静态模式表(INV-SEC-04):已知的敏感环境变量名
- SecretRef 登记(INV-SEC-03):
source: env声明的变量名
路径边界
DenyPaths: []string{
filepath.Join(dataDir, "hypervisor.db"),
filepath.Join(dataDir, "secrets/"),
configFilePath,
}
EnginePaths 定义允许写入的范围,DenyPaths 明确禁止访问的路径。
凭据泄漏扫描
Memory 写入扫描
Store.Save 必须对 entry.Content 运行威胁模式扫描(INV-MEM-24),检测:
- 硬编码密钥模式
- 连接字符串中的密码
- AWS Access Key
- Bearer Token
- Invisible Unicode(混淆攻击)
匹配时返回 ErrThreatPatternDetected,拒绝写入。Always-on,无 opt-out。
读取侧清洗
召回路径通过 SanitizeForRecall 剥离 invisible unicode。
Knowledge 扫描
知识库使用独立扫描器 ScanKBChunk()(INV-KB-SCAN-02),仅检测 private_key(PEM 头)。Per-chunk 粒度——一行 PEM 不杀死整个文档。
流式泄漏扫描
LLM 输出流通过 LeakScan 实时扫描(INV-LEAK-01):
- 每 200 字节扫描一次
- 流结束时对文本和 thinking buffer 各做无条件最终扫描
审计日志
证据链
每次 Run 的工具调用和模型输出记录为 hash chain:
Event[0] → hash(Event[0]) → Event[1] → hash(Event[0..1]) → ...
导出
# JSONL 格式
curl -H "Authorization: Bearer <admin-token>" \
"http://localhost:9091/cells/dept-legal/audit/export?format=jsonl&from=2026-09-01"
# CSV 格式
curl -H "Authorization: Bearer <admin-token>" \
"http://localhost:9091/cells/dept-legal/audit/export?format=csv&from=2026-09-01"
审计摘要
GET /cells/{id}/audit/summary
返回时间范围内的操作统计。
Actor 归因
每次 Run 的 Actor 记录在 wes_run_traces.tags["actor"] 中。Token 用量按 Actor 聚合:
GET /cells/{id}/observe/token-usage?group_by=tag:actor
网络策略
SSRF 防护
internal/infra/ssrf/ 提供 SSRF 检测——阻止 exec 工具和 MCP 代理访问内部网络地址。
DenyPaths
路径级访问控制:
DenyPaths: []string{
"/etc/shadow",
"/root/.ssh/",
dataDir + "/secrets/",
}
exec 网络命令检测
在 NetworkPolicy=deny|internal_only 时,检测 exec 命令中的网络工具(INV-GOV-02):
| 命令 | 检测位置 |
|---|---|
curl, wget | 行首 / ; 分隔符后 / 子 shell 内 |
nc, ncat, netcat | 同上 |
ssh, scp, sftp | 同上 |
rsync | 同上 |
参数位置的同名词(如 grep -r curl .)不误杀。
安全检查清单
部署前
-
spec.key文件权限为0600,目录为0700 -
hypervisor.db不在公共路径 - bootstrap admin token 已记录并妥善保管
- 生产环境使用
env或live源,不用inline - 设置了合适的
DenyPaths - 敏感部门使用
RegulatedPreset
运行时
- 定期轮换 Admin Token
- 监控
degraded_secrets快照 - 审查审计日志导出
- 检查
NetworkPolicy设置
渗透测试要点
| 测试项 | 方法 |
|---|---|
| Token 伪造 | 使用过期/无效/其他 Cell 的 Token |
| 跨 Cell 访问 | 用 Cell A 的 Token 访问 Cell B |
| 路径穿越 | ../../secrets/spec.key |
| 命令注入 | 在 exec 参数中注入 shell 命令 |
| SSRF | 通过 MCP proxy 访问内部地址 |
| 记忆注入 | 写入含恶意 prompt 的记忆 |
| Actor 越权 | 用 admin token 不带 actor 操作私有数据 |
最佳实践
- 最小权限原则——Cell Token 只授予必要的 scope
- 不要把 inline key 用在服务端——用
env或live - Compliance 预设优先——不要手写治理规则
- 定期审计 Token——吊销不再使用的 Token
- 监控凭据降级状态——
degraded_secrets非空需立即处理 - 证据链定期导出——作为合规审计依据
- exec 工具需要治理——敏感环境使用
locked模式