# OpenClaw exec 调通记录
## 背景
本次排查目标是:

本次测试openclaw 生成一个测试文件test24,在/tmp,但是报错没有exec权限。于是测试开始:
- 验证当前会话是否具备 `exec` 执行能力
- 搞清楚为什么执行 shell 命令时总是需要审批
- 定位 OpenClaw 的审批入口
- 最终让 `exec` 成功执行,并完成 `/tmp/test24` 文件创建测试
测试命令主要使用:
```sh
touch /tmp/test24 && ls -l /tmp/test24
```
---
## 一、现象与初始判断
最开始测试 `exec` 时,OpenClaw 没有直接执行命令,而是返回类似信息:
- `Approval required`
- 给出一个审批 ID
- 提示使用 `/approve <id> allow-once|allow-always|deny`
例如:
```text
/approve xxxxxxxx allow-once
```
### 初始现象
1. `read/write/edit` 这类文件工具能直接使用
2. `exec` 即使只是简单命令,也会要求审批
3. 在 Feishu 对话框里发送 `/approve ...` 没有形成有效闭环

### 初步结论
问题不在于 OpenClaw 没有 `exec` 能力,而在于:
- `exec` 被审批机制拦住了
- Feishu 当前聊天窗口不是可靠的审批入口

---
## 二、权限边界测试
为确认边界,做了几类测试:
### 1. 工作区文件写入测试
使用 `write` 工具直接在工作区写文件,成功。
结论:
- 工作区文件操作权限正常
- `write` 工具不依赖 `exec` 审批
### 2. 只读 shell 命令测试
尝试执行:
```sh
pwd
ls -ld /tmp
```
结果:都要求审批。
结论:
- 审批不是只针对“危险命令”
- 而是 `exec` 这条能力整体被审批策略控制

---
## 三、审批入口定位
通过 OpenClaw 文档与实际现象,确认了以下事实:
### 1. Slash commands 由 Gateway 处理
文档说明:
- `/approve ...` 这类 slash command 是由 Gateway 解析的
- 并不保证每个聊天平台都能把 `/...` 当作 OpenClaw 原生命令处理
### 2. Exec approvals 生效位置在执行主机
文档说明:
- gateway host:由 gateway 所在机器执行审批
- node host:由 node 所在机器执行审批
### 3. 审批配置文件位置



审批配置文件位于:
```text
~/.openclaw/exec-approvals.json
```
### 4. 本次实际判断
结合测试现象,确认:
- Feishu 聊天不是稳定的审批入口
- 最可靠入口是 OpenClaw 宿主机上的 CLI / 配置文件
---
## 四、发现 gateway 审批配置为空

在宿主机查看审批配置后,发现文件虽然存在,但内容几乎为空:
```json
{
"version": 1,
"socket": {
"path": "/root/.openclaw/exec-approvals.sock",
"token": "..."
},
"defaults": {},
"agents": {}
}
```
### 这意味着什么
- `socket` 正常
- 但没有默认审批策略
- 没有任何 agent 配置
- 当前主会话 `agent=main`,却没有 `agents.main`
结论:
**审批系统有壳,但没有可用策略。**
---
## 五、先补齐最小可用配置
为了让审批系统先正常工作,先写入了一个保守的最小配置:
```json
{
"version": 1,
"socket": {
"path": "/root/.openclaw/exec-approvals.sock",
"token": "..."
},
"defaults": {
"security": "allowlist",
"ask": "on-miss",
"askFallback": "deny",
"autoAllowSkills": false
},
"agents": {
"main": {
"security": "allowlist",
"ask": "on-miss",
"askFallback": "deny",
"autoAllowSkills": false,
"allowlist": []
}
}
}
```
### 这个配置的效果

- 当前 agent `main` 开始有审批策略
- 命中 allowlist 的命令可直接执行
- 未命中 allowlist 的命令触发审批
### 测试结果
再次测试 `exec` 时,依然会要求审批。
结论:
- 审批系统开始工作了
- 但由于 allowlist 为空,命令还是会被拦
---
## 六、两种放通思路
在确认审批框架工作后,讨论了两种主要方案。

# 方案 A:直接全放行(security = full)
配置思路:
```json
{
"defaults": {
"security": "full",
"ask": "off",
"askFallback": "full",
"autoAllowSkills": true
},
"agents": {
"main": {
"security": "full",
"ask": "off",
"askFallback": "full",
"autoAllowSkills": true,
"allowlist": []
}
}
}
```
## 方案 A 的优点
- 最直接
- 最容易快速验证 `exec` 是否真正可用
- 不依赖逐条维护 allowlist
- 测试时效率最高
## 方案 A 的缺点
- 风险最大
- 基本等于对当前 agent 放开主机 shell 执行能力
- 不适合长期用于生产环境
## 适用场景
- 临时测试
- 自己完全可控的实验环境
- 先验证能力是否通,再收紧权限
---
# 方案 B:保留 allowlist 模式,逐步放行
配置思路:
- `security: allowlist`
- `ask: off` 或 `ask: on-miss`
- 手工维护 allowlist
例如:
```json
{
"defaults": {
"security": "allowlist",
"ask": "off",
"askFallback": "deny",
"autoAllowSkills": false
},
"agents": {
"main": {
"security": "allowlist",
"ask": "off",
"askFallback": "deny",
"autoAllowSkills": false,
"allowlist": [
"/usr/bin/ls",
"/usr/bin/touch"
]
}
}
}
```
## 方案 B 的优点
- 安全性明显更好
- 权限边界清晰
- 适合长期运维场景
- 可以做到“常用命令不弹窗,危险命令不放行”
## 方案 B 的缺点
- 初期维护成本高
- 需要确认实际可执行路径
- shell 命令串、解释器、复合命令可能不如预期那样简单命中
- 如果 allowlist 过小,会频繁 deny 或 ask

## 适用场景
- 长期部署
- 生产环境
- 希望既能用 `exec`,又不想权限过大
---
## 七、中间态:关闭 ask,但仍然 allowlist




在保守配置基础上,还测试/讨论了一个中间模式:
- `security: allowlist`
- `ask: off`
- `allowlist: []` 或较小范围
### 这个模式的行为
- 命中 allowlist:直接执行
- 未命中 allowlist:直接拒绝
- 不再弹审批
这时再测试 `exec`,返回:
```text
exec denied: allowlist miss
```
### 这代表什么
- `exec` 通道本身是正常的
- 不再卡在审批交互上
- 只是命令没有命中白名单
这个阶段是非常关键的诊断节点,说明系统已经从“审批阻塞”切换到“白名单控制”。
---
## 八、最终调通
最终采用的是更宽松的策略,使 `exec` 真正执行成功。

再次执行:
```sh
touch /tmp/test24 && ls -l /tmp/test24
```
得到结果:
```sh
-rw-r--r-- 1 root root 0 4月 2 00:16 /tmp/test24
```
### 最终结论
本次已经确认:
1. OpenClaw 的 `exec` 能力本身是可用的
2. 问题根源在审批/allowlist 配置,而不是工具失效
3. Feishu 当前聊天窗口不是稳定的 `/approve` 执行入口
4. 审批配置应在宿主机通过 CLI 或配置文件管理
5. 当审批策略调整正确后,`exec` 可以成功在目标主机执行命令
---
## 九、方案 A 与方案 B 对比总结
| 方案 | 描述 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 方案 A | `security=full`,接近全放行 | 简单直接、验证最快 | 风险高、权限过大 | 临时测试、实验环境 |
| 方案 B | `security=allowlist`,逐步放行 | 安全、可控、适合长期 | 维护成本高、前期较繁琐 | 生产环境、长期运维 |
### 我的建议
- **短期调试/验证**:先用方案 A,确认能力通了
- **长期上线/正式使用**:改回方案 B,按运维常用命令逐步维护 allowlist
---
## 十、建议的后续动作
### 如果继续追求安全
建议把当前最大放行配置收紧为运维白名单,例如只保留:
- `/usr/bin/ls`
- `/usr/bin/cat`
- `/usr/bin/grep`
- `/usr/bin/find`
- `/usr/bin/touch`
- `/usr/bin/stat`
- `/usr/bin/uname`
- `/usr/bin/whoami`
- `/usr/bin/pwd`
- `/usr/bin/df`
- `/usr/bin/free`
- `/usr/bin/ss`
- `/usr/bin/systemctl`
- `/usr/bin/journalctl`
### 如果继续做验证
可以继续测试:
- `pwd`
- `whoami`
- `uname -a`
- `openclaw status`
- `openclaw gateway status`
- `systemctl status <service>`
用来进一步确认当前 allowlist / full 策略是否符合预期。

---
## 结语
这次调通的关键,不是“如何批准某一个审批 ID”,而是:
**把 OpenClaw exec 的审批体系从空壳状态,调整为真正可工作的策略配置。**
一旦这个底层配置理顺,`exec` 就不再是黑盒,而是一个可控、可验证、可收紧的运维能力。
夜雨聆风