Skip to content

fix(exec): skip gateway cwd injection for remote node host#58977

Merged
steipete merged 6 commits into
openclaw:mainfrom
Starhappysh:fix/exec-skip-gateway-cwd-for-node
Apr 2, 2026
Merged

fix(exec): skip gateway cwd injection for remote node host#58977
steipete merged 6 commits into
openclaw:mainfrom
Starhappysh:fix/exec-skip-gateway-cwd-for-node

Conversation

@Starhappysh

Copy link
Copy Markdown
Contributor

Summary

When exec runs with host=node and no explicit cwd is provided, the gateway injects its own process.cwd() as the default working directory for the remote node. In cross-platform setups (e.g. Linux gateway + Windows node), this Linux path does not exist on Windows, causing:

SYSTEM_RUN_DENIED: approval requires an existing canonical cwd

PR #50961 fixed explicit-cwd path preservation but did not address the omitted-cwd default behavior.

Changes

  • bash-tools.exec.ts: Track whether workdir was explicitly provided by the user or agent config. When host=node and no explicit workdir exists, pass undefined instead of the gateway's process.cwd(), allowing the remote node to use its own default working directory.
  • bash-tools.exec-host-node.ts: Accept workdir as string | undefined. Only send cwd to system.run.prepare when it is defined.
  • bash-tools.exec-approval-request.ts: Update HostExecApprovalParams.workdir type to string | undefined for consistency.

Fixes #58934

Test plan

  • Cross-platform setup: Linux gateway + Windows node, run exec with host=node without explicit cwd -- should succeed using node's default cwd
  • Same setup with explicit cwd -- should still forward the explicit cwd to the node
  • Gateway-only exec (no node) -- behavior unchanged, still uses process.cwd() default
  • Sandbox exec -- behavior unchanged

Co-Authored-By: Claude Opus 4.6 (1M context) [email protected]

@greptile-apps

greptile-apps Bot commented Apr 1, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a cross-platform exec host=node issue where the gateway was injecting its own process.cwd() as the default working directory for a remote node, causing a SYSTEM_RUN_DENIED error when the gateway and node run on different OS platforms (e.g. Linux gateway + Windows node). The fix correctly tracks whether a workdir was explicitly provided, and only forwards it to the remote node when it was — passing undefined otherwise so the node uses its own default.

The logic in bash-tools.exec.ts and bash-tools.exec-host-node.ts is sound. One issue was found: the RequestExecApprovalDecisionParams.cwd field in bash-tools.exec-approval-request.ts was not updated from string to string | undefined alongside HostExecApprovalParams.workdir, creating a TypeScript type mismatch in buildHostApprovalDecisionParams where cwd: params.workdir (string | undefined) is assigned to a cwd: string field.

Confidence Score: 4/5

Mostly safe, but a TypeScript type mismatch in the approval-request types should be fixed before merging to avoid a build failure.

The core fix is correct and well-scoped. However, RequestExecApprovalDecisionParams.cwd was not widened to string | undefined alongside HostExecApprovalParams.workdir, causing buildHostApprovalDecisionParams to produce a type error. This is a P1 build-time issue that needs to be resolved before the PR is ready to merge.

src/agents/bash-tools.exec-approval-request.ts — the RequestExecApprovalDecisionParams.cwd field (line 14) needs to be updated to string | undefined.

Comments Outside Diff (1)

  1. src/agents/bash-tools.exec-approval-request.ts, line 14 (link)

    P1 RequestExecApprovalDecisionParams.cwd not updated to match

    buildHostApprovalDecisionParams (line 213) sets cwd: params.workdir, where params.workdir is now string | undefined. However, RequestExecApprovalDecisionParams.cwd is still typed as cwd: string — a non-optional, non-undefined string. This is a TypeScript type error: assigning string | undefined to a string field will fail a strict-mode compile.

    The cwd field here should be updated to string | undefined (or cwd?: string) to propagate the fix consistently, mirroring what was done to HostExecApprovalParams.workdir.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: src/agents/bash-tools.exec-approval-request.ts
    Line: 14
    
    Comment:
    **`RequestExecApprovalDecisionParams.cwd` not updated to match**
    
    `buildHostApprovalDecisionParams` (line 213) sets `cwd: params.workdir`, where `params.workdir` is now `string | undefined`. However, `RequestExecApprovalDecisionParams.cwd` is still typed as `cwd: string` — a non-optional, non-undefined string. This is a TypeScript type error: assigning `string | undefined` to a `string` field will fail a strict-mode compile.
    
    The `cwd` field here should be updated to `string | undefined` (or `cwd?: string`) to propagate the fix consistently, mirroring what was done to `HostExecApprovalParams.workdir`.
    
    
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/agents/bash-tools.exec-approval-request.ts
Line: 14

Comment:
**`RequestExecApprovalDecisionParams.cwd` not updated to match**

`buildHostApprovalDecisionParams` (line 213) sets `cwd: params.workdir`, where `params.workdir` is now `string | undefined`. However, `RequestExecApprovalDecisionParams.cwd` is still typed as `cwd: string` — a non-optional, non-undefined string. This is a TypeScript type error: assigning `string | undefined` to a `string` field will fail a strict-mode compile.

The `cwd` field here should be updated to `string | undefined` (or `cwd?: string`) to propagate the fix consistently, mirroring what was done to `HostExecApprovalParams.workdir`.

```suggestion
  cwd: string | undefined;
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: src/agents/bash-tools.exec-host-node.ts
Line: 123

Comment:
**Redundant `?? undefined` tail**

`params.workdir` is already typed as `string | undefined`, so the trailing `?? undefined` is a no-op — `undefined ?? undefined` just yields `undefined`.

```suggestion
  const runCwd = prepared.plan.cwd ?? params.workdir;
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix(exec): skip gateway cwd injection fo..." | Re-trigger Greptile

Comment thread src/agents/bash-tools.exec-host-node.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c05131da83

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/agents/bash-tools.exec.ts Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes cross-platform exec failures when running with host=node and no explicit cwd by preventing the gateway from injecting its own process.cwd() into remote node execution requests.

Changes:

  • Track whether workdir was explicitly provided; for host=node with no explicit workdir, forward undefined so the node can use its own default cwd.
  • Update node-host execution plumbing to accept workdir: string | undefined and only include cwd in system.run.prepare when defined.
  • Align exec approval request types to allow workdir to be string | undefined (but see comment about a remaining type mismatch).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
src/agents/bash-tools.exec.ts Avoids forwarding gateway-derived cwd to remote node exec when cwd is omitted.
src/agents/bash-tools.exec-host-node.ts Makes node-host exec accept optional workdir and omits cwd in prepare calls when undefined.
src/agents/bash-tools.exec-approval-request.ts Updates approval request host params to allow optional workdir (currently inconsistent with RequestExecApprovalDecisionParams.cwd).

Comment thread src/agents/bash-tools.exec-approval-request.ts
Comment thread src/agents/bash-tools.exec.ts Outdated
@steipete
steipete force-pushed the fix/exec-skip-gateway-cwd-for-node branch from 295161c to 6dba270 Compare April 2, 2026 15:46
@steipete
steipete force-pushed the fix/exec-skip-gateway-cwd-for-node branch from 6dba270 to 0cb531e Compare April 2, 2026 15:48
@steipete
steipete force-pushed the fix/exec-skip-gateway-cwd-for-node branch from fb68288 to f198470 Compare April 2, 2026 16:00
Starhappysh and others added 6 commits April 2, 2026 18:03
When exec runs with host=node and no explicit cwd is provided, the
gateway was injecting its own process.cwd() as the default working
directory. In cross-platform setups (e.g. Linux gateway + Windows node),
this gateway-local path does not exist on the node, causing
"SYSTEM_RUN_DENIED: approval requires an existing canonical cwd".

This change detects when no explicit workdir was provided (neither via
the tool call params.workdir nor via agent defaults.cwd) and passes
undefined instead of the gateway cwd. This lets the remote node use its
own default working directory.

Changes:
- bash-tools.exec.ts: Track whether workdir was explicitly provided;
  when host=node and no explicit workdir, pass undefined instead of
  gateway process.cwd()
- bash-tools.exec-host-node.ts: Accept workdir as string | undefined;
  only send cwd to system.run.prepare when defined
- bash-tools.exec-approval-request.ts: Accept workdir as
  string | undefined in HostExecApprovalParams

Fixes openclaw#58934

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
…string-only params

After the node early-return, narrow workdir back to string via
resolvedWorkdir for gateway/sandbox paths. Update
buildExecApprovalPendingToolResult and buildApprovalPendingMessage
to accept string | undefined for cwd since node execution may omit it.
Remote node exec may have no explicit cwd when the gateway's own
process.cwd() is omitted. Allow undefined to flow through the
approval request type.
@steipete
steipete force-pushed the fix/exec-skip-gateway-cwd-for-node branch from 9a520a3 to 2a1ecda Compare April 2, 2026 17:04
@steipete
steipete merged commit fc76f66 into openclaw:main Apr 2, 2026
6 of 7 checks passed
@steipete

steipete commented Apr 2, 2026

Copy link
Copy Markdown
Contributor

Landed via temp rebase onto main.

  • Gate: pnpm check; pnpm test -- src/agents/bash-tools.exec.approval-id.test.ts; pnpm test -- src/node-host/invoke-system-run.test.ts; pnpm test -- src/tasks/task-registry.test.ts
  • PR CI: bypassed on maintainer request; follow-up validation on main
  • Land commit: 2a1ecdab17
  • Merge commit: fc76f667c23b63ffa19029a406d61016dd694343

Thanks @Starhappysh!

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2a1ecdab17

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread CHANGELOG.md
- Telegram/exec approvals: rewrite shared `/approve … allow-always` callback payloads to `/approve … always` before Telegram button rendering so plugin approval IDs still fit Telegram's `callback_data` limit and keep the Allow Always action visible. (#59217) Thanks @jameslcowan.
- Cron/exec timeouts: surface timed-out `exec` and `bash` failures in isolated cron runs even when `verbose: off`, including custom session-target cron jobs, so scheduled runs stop failing silently. (#58247) Thanks @skainguyen1412.
- Telegram/exec approvals: fall back to the origin session key for async approval followups and keep resume-failure status delivery sanitized so Telegram followups still land without leaking raw exec metadata. (#59351) Thanks @seonang.
<<<<<<< HEAD

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove unresolved merge-conflict marker from changelog

The changelog entry includes a literal merge-conflict marker (<<<<<<< HEAD), which is an accidental artifact rather than release-note content. Leaving this in place pollutes user-facing release notes and can break any tooling that parses changelog bullets for automation or publishing.

Useful? React with 👍 / 👎.

steipete added a commit to duncanita/openclaw that referenced this pull request Apr 4, 2026
lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
Nachx639 pushed a commit to Nachx639/clawdbot that referenced this pull request Jun 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Validation Failure when Using exec with host=node and cwd is Omitted (Gateway Path Inheritance)

3 participants