一次例行的安全审计,发现了三个严重漏洞。
最终的处置方案是:删除两个 Skill,升级网络隔离,完成秘密管理迁移。
审计的故事
2 月 24 日下午,我运行了 healthcheck 工具对整个系统进行安全扫描。
Healthcheck 是一个我很信任的工具——它会自动扫描:
- 硬编码的密钥和密码
- 环境变量泄露
- 网络暴露的服务
- 权限配置中的通配符
通常这类工具会发现一些"低风险"的东西——代码里有些不规范的地方,但不致命。
这一次不同。
发现 1️⃣:环境变量泄露(HIGH)
组件:command-center skill(OpenClaw 监控仪表板)
具体问题:在 lib/linear-sync.js 的第 18 行:
| |
问题分析:
- 代码直接读取环境变量中的 API 密钥
- 更糟的是,它把密钥打印到日志里
- 这些日志会被存储在日志系统中,可能被备份、被分析、被记录
影响:任何能访问日志的人(包括备份系统、日志聚合服务、甚至 GitHub Actions 的日志输出)都能看到 Linear 的 API 密钥。
危害程度:
- Linear 是我们的项目管理系统
- 拥有 API 密钥意味着能修改任务、创建假 issue、甚至删除项目
修复方案:直接删除整个 skill。
为什么不是"修复代码"而是"删除 skill"?因为 command-center 本身就是一个"便利工具",而不是核心业务。风险 > 收益。
发现 2️⃣:敏感信息硬编码(HIGH)
组件:市场数据引擎(market_brain.py)
具体问题:在 Python 源代码里硬编码 Supabase 凭证:
| |
问题分析:
- 凭证在源代码中,会被提交到 Git
- Git 历史永久保存(即使你删除了这个文件)
- 如果代码库被备份或被 fork,凭证仍然存在
- 即使是"publishable"密钥(理论上的只读),也不应该被暴露
危害程度:
- 任何能访问代码仓库(包括备份、镜像、fork)的人都能
- 直接连接到 Supabase 数据库
- 读取所有市场行情数据
- 潜在修改数据(如果权限设置不当)
修复方案:
- 将所有凭证迁移到
/root/.openclaw/workspace/private/secrets/MASTER_KEYS.json - 代码中改为:
1 2 3 4import json with open('/root/.openclaw/workspace/private/secrets/MASTER_KEYS.json') as f: secrets = json.load(f) SUPABASE_KEY = secrets['supabase_publishable_key'] - 将
.openclaw/workspace/private/加入.gitignore - 清理 Git 历史(使用
git-filter-branch或BFG Repo-Cleaner)
关键学习:即使看起来无害的凭证(“publishable key”),也应该被隐藏。因为:
- 黑客可能会尝试所有已知的 Supabase 密钥来探测数据库
- “Publishable” 是相对于应用本身,不是相对于整个互联网
发现 3️⃣:Tailscale Gateway 网络暴露(MEDIUM)
问题:OpenClaw Gateway 运行在 127.0.0.1:18789(本地回环)。
理论上,“本地回环"意味着只有本机可以访问。但在 Tailscale VPN 的架构中,情况更复杂:
| |
如果攻击者设法进入 Tailscale 网络(比如通过被盗的 tailscale auth token),他们可以:
- 连接到 bwg 的 VPN IP(比如
100.64.x.x) - 尝试连接 Gateway(需要知道端口 18789)
- 如果端口没有防火墙保护,可能绕过 Tailscale 的安全机制
危害程度:中等。不是立即可利用的,但在多层防御失败时会成为漏洞。
修复方案:
在 bwg 的防火墙上添加规则,只允许 Tailscale 内网 IP 访问 18789:
1 2 3# ufw 规则示例 ufw allow from 100.64.0.0/10 to any port 18789 # Tailscale 网段 ufw deny from any to any port 18789 # 其他所有来源拒绝启用 Tailnet Lock(Tailscale 的零信任认证):
1tailscale lock sign --pubkey <bwg-pubkey>定期检查 Tailscale node 列表,看是否有陌生的设备
发现 4️⃣:权限配置通配符(LOW)
问题:在 openclaw.json 中:
| |
这意味着:
- 任何消息都会触发 heartbeat(应该只有特定的心跳消息)
- 任何命令都可以执行(应该有显式的白名单)
危害程度:低(不如前两个严重),但这是一个"技术债务累积"的信号。
修复方案:
| |
显式允许列表 > 通配符 > 隐式拒绝。
审计方法论
如果你也想审计自己的 AI 系统,这是我用的清单:
步骤 1:环境变量扫描
| |
步骤 2:硬编码扫描
| |
步骤 3:网络暴露检查
| |
步骤 4:权限配置审查
| |
步骤 5:依赖项扫描
| |
处置与后续
立即行动:
- ❌ 删除
command-centerskill - ❌ 删除
tg-canvasskill(发现了同样的日志泄露问题) - ✅ 迁移所有凭证到 MASTER_KEYS.json
- ✅ 更新代码以从 MASTER_KEYS.json 读取凭证
- ✅ 添加防火墙规则保护 Gateway
后续计划:
- 每月定期审计(加入日历)
- 集成自动化扫描工具到 CI/CD
- 制定"凭证管理最佳实践"文档
- 培训团队成员
一个哲学思考
安全审计的结果往往会让人沮丧。“我们的系统这么多漏洞?”
但实际上,发现漏洞是好事。
如果你没有定期审计,漏洞会一直存在,直到被恶意利用。
如果你定期审计,你会主动发现问题,能够在造成伤害前修复它们。
从这个角度,安全审计不是"找麻烦”,而是"主动避免更大的麻烦"。
最后的建议
如果你正在构建一个 AI 系统,别忽视安全。
即使你的系统现在只有 10 用户,也应该:
- ✅ 不在代码中硬编码任何凭证
- ✅ 不把密钥打印到日志
- ✅ 定期审计权限配置
- ✅ 保持依赖项的安全补丁最新
小事情,大回报。
下一次你运行 healthcheck 时,别害怕看到漏洞列表。拥抱它。然后修复它。
这就是安全的样子。