#Running a Python script in Node

1 messages · Page 1 of 1 (latest)

vernal turtle
#

Hi @waxen coyote, my agents are trying to run a Python script from inside a paired Node.

The node allowlist includes both python3 as well as the path to the Python interpreter binary.
The agent is not in a sandbox,
The agent is in the default harness.
The gateway.tools.allowlist config includes all the groups except for web

The error: SYSTEM_RUN_DENIED: approval cannot safely bind this interpreter/runtime command.

What other details do you need to help me debug this?

waxen coyoteBOT
#

Yep — this specific error is usually not “Python isn’t allowlisted.” It means OpenClaw reached the node, but the exec approval layer couldn’t safely bind the Python/runtime command to one concrete script file.

Most useful details:

openclaw --version
openclaw nodes status
openclaw nodes describe --node <id-or-name>
openclaw approvals get --node <id-or-name>
openclaw config get tools.exec

And please paste/redact:

  1. The exact command the agent is trying to run.
    • Especially whether it’s python3 script.py vs python3 -c ..., heredoc/stdin, python3 -m ..., sh -lc "python3 ...", package scripts, etc.
  2. The cwd/workdir used for the exec call.
#
  1. Whether the script exists on the node machine at that path.
  2. Whether this is macOS companion app node or headless openclaw node run.
  3. The relevant denial lines from logs, if any.

Quick likely test: try a direct file invocation like:

python3 /absolute/path/to/script.py

If inline/stdin forms like python3 - <<'PY' or python3 -c ... are being used, this denial is expected in approval-backed/allowlist mode because there’s no stable single file to bind.

Docs: https://docs.openclaw.ai/tools/exec-approvals and https://docs.openclaw.ai/tools/exec-approvals-advanced#interpreterruntime-commands 🦐

vernal turtle
#

On it brb

waxen coyoteBOT
#

Sounds good — I’ll wait. 🦐

vernal turtle
#

Here's the diagnostic summary:

1. command attempted:

python3 /Users/__REDACTE__.py --log-note "2026-04-28 requested staging"

2. CWD/workdir: Default (current session working directory — no explicit workdir override)

3. Script path: /Users/__REDACTED__.py — exists on the host at that path.

4. Node type: macOS companion app node (platform: darwin, clientMode: node) — node ID 20…f8 .

5. Denial lines:

INVALID_REQUEST: SYSTEM_RUN_DENIED: approval cannot safely bind this interpreter/runtime command
waxen coyoteBOT
#

That’s enough to narrow it down.

This looks like a current approval-backed node exec limitation, not a missing allowlist entry.

Even though your command is:

python3 /Users/...py --log-note "..."

exec host=node wraps node commands as roughly:

/bin/sh -lc '<your command>'

In approval/allowlist mode, OpenClaw refuses interpreter/runtime commands hidden inside a shell payload because it can’t safely bind the approval to exactly one stable script file. So allowlisting python3 alone won’t fix this.

#

Likely workarounds:

  1. Trusted node / YOLO exec policy
    If this node is trusted, set both requested exec policy and node approvals to security: full, ask: off.

  2. Avoid approval-backed node exec for this path
    Run it in a sandbox/gateway context instead, or restructure through a trusted wrapper/automation boundary.

  3. File as limitation/bug if you expected direct Python file calls to work via node exec
    This is probably worth a GitHub issue with your exact summary: https://github.com/openclaw/openclaw/issues

One thing I’d still check:

openclaw --version
openclaw approvals get --node 20…f8
#

If effective node policy is allowlist or ask: on-miss/always, this denial is expected from the current binding logic.

vernal turtle
#

One of the issues here is that the script is from a family of scripts that have to use Node due to dependencies

waxen coyoteBOT
#

Ah, yep — if the dependency reason means “this has to run on the paired Mac node,” then this is mostly a trust-boundary/design choice rather than a Python allowlist tweak.

Important distinction: gateway.tools.allowlist controls whether the agent has the exec tool. This denial is later, inside the node exec approvals layer.

Practical options:

  1. Trusted node mode
    If that Mac node is trusted for this agent, set the node exec approval policy to security: full / ask: off. That’s the cleanest path for “run my local dependency-heavy scripts.”

  2. Move deps to gateway/sandbox
    If you want approvals/allowlist to stay strict, run the scripts somewhere OpenClaw doesn’t need host=node shell-wrapping.

  3. Narrow node-side wrapper
    Put a constrained, trusted CLI/wrapper on the node that only exposes the safe operation/args you need. Don’t make it an arbitrary “run any Python script” wrapper unless you’re comfortable with that trust level.

  4. File this as a limitation
    Current exec host=node string commands are shell-wrapped, so a bindable direct argv like:

#
   ["/usr/bin/python3", "/Users/...py", "--log-note", "..."]

isn’t what the approval binder sees. That’d be a good GitHub issue/request: https://github.com/openclaw/openclaw/issues

If these are actually Node.js scripts (node script.js) rather than “paired node” scripts, same family of limitation applies in approval-backed mode.

vernal turtle
#

So the best option appears to be to put the Node in YOlO mode and file an issue. Can you help me draft the issue report, please? Also check if there are any related issues to tag. Thank you, @waxen coyote

waxen coyoteBOT
#

Yep — I’d do YOLO only if that Mac node is fully trusted, then file this as a “node exec approval binding too conservative / no direct argv path” issue.

YOLO reminder: node approvals are separate; openclaw exec-policy preset yolo does not sync node approvals, so use:

openclaw config set tools.exec.host node
openclaw config set tools.exec.security full
openclaw config set tools.exec.ask off
openclaw gateway restart

openclaw approvals set --node 20…f8 --stdin <<'EOF'
{
  version: 1,
  defaults: {
    security: "full",
    ask: "off",
#
    askFallback: "full"
  }
}
EOF

Docs say node-targeted approval updates need openclaw approvals --node, and YOLO requires both tools.exec.* and host/node approvals to be open. (github.com)

Related issues I found:

  • #7013 — node exec approvals denied despite wildcard allowlist; closed, older, related approval/allowlist confusion. (github.com)
  • #44487exec host=node regressions around node exec / cwd / full policy forwarding; closed but relevant context. (github.com)
  • #62115 — open, broader exec/full-profile failure; only tangential unless YOLO still fails or returns empty output. (github.com)

Draft issue:

GitHub

Your own personal AI assistant. Any OS. Any Platform. The lobster way. 🦞 - Issues · openclaw/openclaw

GitHub

Your own personal AI assistant. Any OS. Any Platform. The lobster way. 🦞 - Issues · openclaw/openclaw

GitHub

Your own personal AI assistant. Any OS. Any Platform. The lobster way. 🦞 - Issues · openclaw/openclaw

#
## Summary

`exec host=node` on a macOS companion app node denies a direct Python script invocation with:

`SYSTEM_RUN_DENIED: approval cannot safely bind this interpreter/runtime command`

The command is a direct interpreter + absolute script path invocation, and the script exists on the node host:

```bash
python3 /Users/<redacted>.py --log-note "2026-04-28 requested staging"

This appears to happen because node exec routes string commands through /bin/sh -lc, so the approval binder sees an interpreter/runtime inside a shell payload and refuses to bind it, even though the underlying operation has a concrete script file.

Environment

#

- OpenClaw version: `<paste openclaw --version>`
- Gateway OS: `<paste>`
- Node type: macOS companion app node
- Node platform: `darwin`
- Node clientMode: `node`
- Node id: `20…f8`
- Agent harness: default harness
- Agent sandbox: disabled / not sandboxed
- `tools.exec.host`: `node`
- Effective node approval policy: `<paste redacted output of openclaw approvals get --node 20…f8>`

## Reproduction

1. Pair a macOS companion app node.
#
2. Configure `exec host=node`.
3. Put node exec approvals in allowlist / approval-backed mode.
4. Add allowlist entries for:
   - `python3`
   - the resolved Python interpreter path
5. Ask the agent to run:

```bash
python3 /Users/<redacted>.py --log-note "2026-04-28 requested staging"

The script exists at that absolute path on the macOS node.

Expected behavior

#
A direct interpreter invocation with one concrete absolute script operand should either:

1. be safely approval-bound to that script file and run, or
2. have a documented supported way to submit direct argv to node exec without shell wrapping, e.g.:

```json
["/usr/bin/python3", "/Users/<redacted>.py", "--log-note", "2026-04-28 requested staging"]

Actual behavior

The command is denied:

INVALID_REQUEST: SYSTEM_RUN_DENIED: approval cannot safely bind this interpreter/runtime command
#

Allowlisting `python3` and the Python interpreter path does not resolve it.

## Impact

This blocks dependency-heavy local workflows that must run on the paired macOS node rather than the gateway/sandbox. The only working option appears to be putting the node in full/YOLO mode, which is broader than desired.

## Suspected cause

`exec host=node` wraps string commands as shell payloads on POSIX nodes, roughly:

```bash
/bin/sh -lc "<user command>"
#
The approval binder then treats the interpreter/runtime invocation as hidden inside a shell payload and refuses to bind the approval to the concrete script file.

## Related issues

- Related: #7013
- Related: #44487
- Possibly related if YOLO/full mode still fails: #62115

## Workaround

Set the trusted node to YOLO/full mode:

```bash
openclaw config set tools.exec.host node
openclaw config set tools.exec.security full
openclaw config set tools.exec.ask off
#

openclaw gateway restart

openclaw approvals set --node <node-id> --stdin <<'EOF'
{
version: 1,
defaults: {
security: "full",
ask: "off",
askFallback: "full"
}
}
EOF

I’d title it: exec host=node denies direct Python script: approval cannot safely bind interpreter/runtime command.

vernal turtle
#

@waxen coyote thank you! I will mark the solution above once I verify node YOlO mode does the trick

waxen coyoteBOT
#

Perfect — hope YOLO mode gets you unstuck. 🦐

If it still denies after that, the key thing to re-check is:

openclaw approvals get --node <node-id>

Make sure the effective node policy says security: full and ask: off, not just the gateway config.

vernal turtle
#

@waxen coyote when I run this:

openclaw approvals set --node 20__REDACTED__8 --stdin <<'EOF' { version: 1, defaults: { security: "full", ask: "off", askFallback: "full" } } EOF

I get this error:

│ { version: 1, defaults: { security: "full", ask: "off", askFallback: "full" } } ◇ │ ◇ Failed to parse approvals JSON: SyntaxError: JSON5: invalid end of input at 1:1

waxen coyoteBOT
#

That parse error usually means the CLI received empty/truncated stdin — likely the heredoc didn’t survive copy/paste cleanly.

Use a temp file instead; it’s less fragile:

cat > /tmp/openclaw-node-yolo.json5 <<'EOF'
{
  version: 1,
  defaults: {
    security: "full",
    ask: "off",
    askFallback: "full"
  }
}
EOF
#
openclaw approvals set --node "20__REDACTED__8" --file /tmp/openclaw-node-yolo.json5
openclaw approvals get --node "20__REDACTED__8"

If you retry --stdin, make sure EOF is alone on its own line, with no indentation/trailing spaces/backticks:

openclaw approvals set --node "20__REDACTED__8" --stdin <<'EOF'
{
  version: 1,
  defaults: {
    security: "full",
    ask: "off",
    askFallback: "full"
  }
#
}
EOF

Afterwards, verify the effective policy shows security: full and ask: off.

vernal turtle
#

@Krill that wiped my exec-approvals.json file clean.

waxen coyoteBOT
#

Oof — you’re right. That’s on me. openclaw approvals set replaces the whole exec-approvals file, it doesn’t merge defaults. I should have warned you clearly.

First, preserve the current state:

openclaw approvals get --node "20__REDACTED__8" --json > ~/openclaw-approvals-after-wipe.json

Then check if there’s any backup/older copy on the Mac node:

find ~/.openclaw -maxdepth 2 -iname '*exec-approvals*' -print

If there’s no backup, recovery is basically reconstructing from:

  • any previous openclaw approvals get --node ... output
  • terminal scrollback
#
  • Time Machine / filesystem backup
  • re-adding allowlist entries manually

For YOLO mode, the minimal file is still valid, but yes, previous per-agent allowlists are gone unless restored/recreated.

If you paste the old/current approvals get --node ... output if you have it, I can help reconstruct a proper file that preserves your agents/allowlists and only changes the defaults.

vernal turtle
#

@waxen coyote I have backup. Its okay. Tell me exactly how to edit the file directly instead.

waxen coyoteBOT
#

Yes — edit it on the Mac node machine itself, not via approvals set.

Also important: the file on disk must be strict JSON, not JSON5. So keys need quotes.

Safest direct patch:

cd ~/.openclaw
cp exec-approvals.json "exec-approvals.json.bak.$(date +%Y%m%d-%H%M%S)"

node <<'NODE'
const fs = require("fs");
const p = `${process.env.HOME}/.openclaw/exec-approvals.json`;

const f = JSON.parse(fs.readFileSync(p, "utf8"));
f.version = 1;
#
f.defaults = {
  ...(f.defaults || {}),
  security: "full",
  ask: "off",
  askFallback: "full"
};

fs.writeFileSync(p, JSON.stringify(f, null, 2) + "\n");
fs.chmodSync(p, 0o600);
console.log(`Updated ${p}`);
NODE

Then verify:

#
node -e 'JSON.parse(require("fs").readFileSync(process.env.HOME + "/.openclaw/exec-approvals.json", "utf8")); console.log("valid JSON")'

openclaw approvals get --node "20__REDACTED__8"

You want the effective policy to show security: full and ask: off.

If editing manually, only change/add this block and leave socket + agents untouched:

"defaults": {
  "security": "full",
  "ask": "off",
  "askFallback": "full"
}
vernal turtle
#

@waxen coyote can i set these as overrides for a specific agent?

waxen coyoteBOT
#

Yes — but for this case you need both layers set for that agent:

  1. Gateway requested exec policy for that agent.
  2. Node host approvals file for that same agent.

If only the node approvals file says YOLO but gateway config still requests allowlist, OpenClaw may still hit the approval-binder path.

1. On the Mac node: edit ~/.openclaw/exec-approvals.json

AGENT_ID=main node <<'NODE'
const fs = require("fs");
const p = `${process.env.HOME}/.openclaw/exec-approvals.json`;
const agentId = process.env.AGENT_ID || "main";

const f = JSON.parse(fs.readFileSync(p, "utf8"));
#
f.version = 1;
f.agents ||= {};
f.agents[agentId] = {
  ...(f.agents[agentId] || {}),
  security: "full",
  ask: "off",
  askFallback: "full"
};

fs.writeFileSync(p, JSON.stringify(f, null, 2) + "\n");
fs.chmodSync(p, 0o600);
console.log(`Updated ${p} for agent ${agentId}`);
NODE

2. On the gateway: set that agent’s requested exec policy

#

Find the agent index:

openclaw config get agents.list

Then, for the matching agent index, e.g. [0]:

openclaw config set agents.list[0].tools.exec.host node
openclaw config set agents.list[0].tools.exec.node "20__REDACTED__8"
openclaw config set agents.list[0].tools.exec.security full
openclaw config set agents.list[0].tools.exec.ask off
openclaw gateway restart

Then verify:

#
openclaw approvals get --node "20__REDACTED__8"

If this is the default agent, the agent id is probably main.

vernal turtle
#

@waxen coyote YOLO mode is indeed what fixed this. Anytime I tried to reintroduce some sanity, the commands failed again for the same reasons.

For anybody dealing with this, here was the fix:

  1. Update openclaw.json
"tools:"
    "exec": {
      "host": "node",
      "security": "full",
      "ask": "off"
},
"agents":
  "list": [ // or "defaults"
    "exec": {
      "host": "node",
      "node": "my-node-id",
      "security": "full",
      "ask": "off"
    }
  ]
  1. Update exec-approvals.json
  "defaults": {
    "security": "full",
    "ask": "off",
    "askFallback": "full",
    "autoAllowSkills": true
  },