欢迎光临
我们一直在努力

OpenClaw security audit 实测 32 个配置:10 个报 critical,退出码一次都没变

OpenClaw security audit 实测 32 个配置:10 个报 critical,退出码一次都没变

数据采集时间:2026-10-26 14:00–14:20(Asia/Shanghai)。更新时间:2026-10-26 14:20。 本文只测本机 OpenClaw 2026.10.7 (157d8c2) 的 openclaw security audit。32 个配置场景全部在隔离的 HOME 目录下执行,每个场景只写一份 ~/.openclaw/openclaw.json,然后运行 openclaw security audit --json,记录退出码、summary 与每一条 checkId。命令和原始消息都附在文中,可以逐条复算;没有直接测到的部分标 UNKNOWN。

OpenClaw 文档站 Security CLI 页「What --fix changes」段落实拍:说明 --fix 只收紧 groupPolicy 与文件权限,不轮换 token、不改 gateway bind/auth,2026-10-26

一、结论先说

32 个场景里,10 个至少报出一条 critical,19 个只报 warn,2 个做到 0 critical / 0 warn。 但 security audit 的退出码在这些场景里一次都没变过:31 个配置合法的场景全部 exit 0,包括那 10 个带 critical 的;唯一一次 exit 1 是配置文件本身无效、审计根本没跑起来。

换句话说,它是一份给人读的体检报告,不是一个能给 CI 当门禁的返回值。想用退出码判断”这台机器安不安全”,&& 后面接部署脚本,等于什么都没拦。

它拦得住的东西很具体:gateway.bind="lan" 却没有 token/password、lan 绑定下 Control UI 没有 origin 白名单、令牌短于阈值、配置文件 0666、state 目录 0777、hooks 令牌太短、exec 被设成 security=full。它放过去的东西同样具体:tools.elevated.enabled=true、browser.noSandbox=true、plugins.load.paths 指向根目录,以及明文的 Telegram botToken。

二、测试口径

  • 版本:openclaw --version 输出 OpenClaw 2026.10.7 (157d8c2),Node v24.22.1。
  • 隔离:每个场景一个独立 HOME,配置路径经 openclaw config file 确认落在该 HOME 的 .openclaw/openclaw.json。
  • 判定:只认 --json 里的 summary 和 findings[].checkId,不按人类可读文案猜。
  • 覆盖:18 个网络/权限/钩子/插件场景,7 个文档所列”危险开关”场景,5 个补充对照,2 个干净基线,外加 2 次 --fix 实验。
  • 复现一个场景只需要三行:

export HOME=$PWD/.openclaw/tmp/audit/home
mkdir -p "$HOME/.openclaw"
printf '%s' '{"gateway":{"bind":"lan","auth":{"mode":"none"}}}' > "$HOME/.openclaw/openclaw.json"
openclaw security audit --json | jq '.summary'

本机真实 ~/.openclaw 不在测试范围内:上面每个 HOME 都是临时目录,测完即弃。

三、整体分布

OpenClaw 文档站 Security audit checks 页开头实拍:findings 以 checkId 为键,--deep 才跑 plugin/skill 代码扫描与 Gateway 探针,2026-10-26
观测项 数值
配置场景 32
配置合法并产出报告 31
配置无效、审计中止 1(tools.exec.mode 与 security 同时出现)
含 ≥1 条 critical 10
只有 warn 19
0 critical / 0 warn 2
出现过的不同 checkId 21
文档目录里收录的 checkId 131
退出码非 0 1(即那条无效配置)

出现频次最高的三条:gateway.trusted_proxies_missing(24/32)、gateway.http.no_auth(5/32)、gateway.control_ui.allowed_origins_required(5/32)。summary.attack_surface 是每次都会带的 info,不算问题。

四、它拦得住什么

挑几组最能说明”严重度分级不是装饰”的结果:

场景 结果
空 HOME,连配置文件都没有 1 critical + 2 warn:gateway.loopback_no_auth、gateway.trusted_proxies_missing、gateway.http.no_auth
bind=lan + auth.mode=none 3 critical:gateway.bind_no_auth、gateway.control_ui.allowed_origins_required、gateway.http.no_auth;另 1 warn gateway.auth_no_rate_limit
bind=lan + token(32 字符) 仍 1 critical:gateway.control_ui.allowed_origins_required
bind=lan + password(23 字符) 1 critical(同上)+ 3 warn:gateway.password_too_short、gateway.auth_no_rate_limit、config.secrets.gateway_password_in_config
配置 0666 1 critical:fs.config.perms_writable(原文写明”其他用户可改 gateway/auth/tool 策略”)
state 目录 0777 1 critical:fs.state_dir.perms_world_writable
配置文件 0644 且含明文 botToken 1 critical:fs.config.perms_world_readable

两个细节值得记下来。

第一,空配置就有 1 条 critical。gateway.loopback_no_auth 的判定条件是”绑定 loopback 且没配 auth secret”,没有配置文件时同样成立。刚装完还没跑 openclaw setup 的机器,第一次体检不会是绿的。

第二,加了 token 不等于 lan 绑定就安全。31 个场景里 gateway.control_ui.allowed_origins_required 出现了 5 次,其中 2 次是在 token / password 都配好的情况下——审计认为非 loopback 绑定下 Control UI 缺少浏览器来源白名单本身就是 critical,和”有没有密码”是两件事。

想真正做到 0 critical / 0 warn,我试了两组:loopback + token + 非空 trustedProxies,以及 lan + token + rateLimit + publicOrigin + controlUi.allowedOrigins。两组都是 0/0,只留一条 info。所以”干净”是可达的,只是要多配 2 到 5 个键。

五、它放过了什么

这部分比第四节更重要,因为它决定了你不能把 security audit 当成唯一的安全检查。

1)提权工具开关不报。 tools.elevated.enabled=true,结论是 0 critical、1 warn(gateway.trusted_proxies_missing,与开关无关)。更微妙的是 summary.attack_surface 的正文:默认配置和打开提权后的正文逐字相同,都写着 tools.elevated: enabled。也就是说,这条 info 不能用来判断提权是不是被显式打开过。

2)浏览器不沙箱不报。 browser.noSandbox=true,同样只有那条 trusted_proxies_missing。配置 schema 里这个字段的说明写着”尽可能保持关闭,因为进程隔离保护会被削弱”——schema 有警告,审计没有对应 finding。

3)插件扫描路径给到根目录不报。 plugins.load.paths=["/"] 的结果和基线完全一样。schema 里这个字段的说明提醒”避免宽泛路径夹带无关可执行内容”,审计侧没有检查。

4)明文渠道令牌不按”密钥落盘”报。 把 Telegram botToken 明文写进配置、文件权限 0600,审计给的是 0 critical、1 warn(还是那条 trusted_proxies),没有任何 config.secrets.* 相关 finding。同一份配置改成 0644,才多出一条 fs.config.perms_world_readable critical。作为对照:gateway.auth.password 明文落盘会报 config.secrets.gateway_password_in_config(warn),hooks.token 明文落盘会报 config.secrets.hooks_token_in_config(info)。三个都是长期凭据,只有两个进了”密钥落盘”检查。

5)hooks 打开但完全没配 token,也不报”缺令牌”。 hooks.enabled=true 且不给 token,得到 2 条 warn:hooks.default_session_key_unset、hooks.allowed_agent_ids_unrestricted。反而是给一个 3 字符的短 token 时会多一条 hooks.token_too_short——配了烂令牌比压根不配令牌多一条警告。这条 ingress 到底怎么鉴权,本文没有实测(UNKNOWN),只记录审计层面的表现。

六、退出码:0 不代表安全

这是最容易被自动化踩到的一点。10 个带 critical 的场景,退出码全是 0;--deep 在没有运行中 Gateway 时也返回 0,只多一条 warn gateway.probe_failed。

唯一一次 exit 1 是配置读取阶段就失败:


# tools.exec.mode 与 tools.exec.security 同时出现
openclaw security audit --json   # exit 1

原文消息是 tools.exec.mode: mode cannot be combined with security or ask in the same exec object。顺带说明:这一条 openclaw config validate --json 也会判 valid: false、退出码 1,两个命令在这件事上一致。

要给流水线加门禁,应该解析 JSON 而不是看退出码,例如:


openclaw security audit --json | jq -e '.summary.critical == 0'

七、–fix 与 doctor –fix 的边界

OpenClaw 文档站 Network exposure 页 Insecure/dangerous flags 段落实拍:每个启用的危险开关单独发一条 config.insecure_or_dangerous_flags,2026-10-26

--fix 只修权限这类确定性动作。 对一个 0666 的配置跑 openclaw security audit --fix:文件权限从 0666 变成 0600,再跑一次审计,fs.config.perms_writable 消失,剩 1 warn;修复输出里 configWritten: false,changes: [],actions 只有一条 chmod。

对 bind=loopback + auth.mode=none 跑同样的 --fix:配置文件一个字节都没变,critical 原样留着。这和文档一致——--fix 明确”不轮换 token/password、不改 gateway bind/auth/network”。

doctor --fix 会重写整份配置。 把已退休的 gateway.controlUi.dangerouslyDisableDeviceAuth 写进配置后运行 openclaw doctor --fix,这个键确实被删掉了(controlUi 变成 {}),但文件从 157 字节涨到 2,468 字节:多出 agents.entries.main、meta.migrations、wizard 记录,以及 34 个 skills.entries 的 enabled: false 默认项。文档说这个键”retired, inert”,说 doctor 会移除它,两点都成立;但”移除一个键”的实际副作用是把配置文件按当前版本模板补齐。在真实机器上跑之前,先备份。

八、文档对账:131 个 checkId,6 个”今天会被跟踪”的开关

文档 Security audit checks 页共列出 131 个 checkId(含 browser.* 这类通配条目)。本次 32 个场景只触发了 21 个,其余没触发不代表不存在,只代表我的配置没碰到——这一点必须说清楚。

Network exposure 页有一个折叠块,标题是”Flags tracked by the audit today”,列了 6 项。逐项测:

文档所列开关 是否产生 finding
gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true 是:config.insecure_or_dangerous_flags + 专属 gateway.control_ui.host_header_origin_fallback
security.audit.suppressions configured 是:config.insecure_or_dangerous_flags + security.audit.suppressions.active
hooks.gmail.allowUnsafeExternalContent=true 是
hooks.mappings[].allowUnsafeExternalContent=true 是(原文写作 hooks.mappings[0].allowUnsafeExternalContent=true)
tools.exec.applyPatch.workspaceOnly=false 是
plugins.entries.acpx.config.permissionMode=approve-all 否:本机未安装 acpx 插件,配置合法但审计无任何 finding

另外测了文档在”所有 dangerous\*/dangerously\* 键”清单里列出、但没有写进那 6 项的一个键:browser.ssrfPolicy.dangerouslyAllowPrivateNetwork=true。结果是会产生 config.insecure_or_dangerous_flags finding。所以那 6 项清单至少漏了一项;反过来,acpx 那一项在插件未安装时不生效,审计没法替你做”插件级权限”判断。

九、给你的三条实用结论

  1. 别用退出码做门禁,用 jq -e '.summary.critical == 0',否则 10 次 critical 全会静默通过。
  2. session 里默认就有 security.audit.suppressions.active 这条 info:一旦你为了”让报告变绿”加了 suppression,输出里会一直留痕,这是好事——说明有人主动接受过风险,而不是风险消失。
  3. 体检报告要和 schema 说明一起读。tools.elevated、browser.noSandbox、plugins.load.paths 三项,schema 里都写着”谨慎开启”,审计却一条都不报。这三项属于”配置设计层面的取舍”,只能靠人读。

十、数据与来源

  • 版本与命令:本机 openclaw --version = OpenClaw 2026.10.7 (157d8c2),Node v24.22.1,采集时间 2026-10-26 14:00–14:20 +08:00。
  • 文档:https://docs.openclaw.ai/cli/security、https://docs.openclaw.ai/gateway/security/audit-checks、https://docs.openclaw.ai/gateway/security/network-exposure,同一时段抓取;131 个 checkId 是从 audit-checks 表格里数出来的。
  • 截图:三张都是上述文档页在 Chrome 无头模式、1440×950 视口下的实际渲染,未做裁剪以外的修改。
  • 未测:真实 Gateway 的 --deep 联网探针、插件代码扫描、真实渠道令牌的鉴权行为。这些标 UNKNOWN,本文不做推断。
赞(0)
未经允许不得转载:时间网 » OpenClaw security audit 实测 32 个配置:10 个报 critical,退出码一次都没变

更好的WordPress主题

支持快讯、专题、百度收录推送、人机验证、多级分类筛选器,适用于垂直站点、科技博客、个人站,扁平化设计、简洁白色、超多功能配置、会员中心、直达链接、文章图片弹窗、自动缩略图等...

联系我们联系我们

登录

找回密码

注册