Skip to content

fix(gateway): skip local workdir resolution for remote node execution#50961

Merged
obviyus merged 3 commits intoopenclaw:mainfrom
openperf:fix-exec-node-workdir
Mar 29, 2026
Merged

fix(gateway): skip local workdir resolution for remote node execution#50961
obviyus merged 3 commits intoopenclaw:mainfrom
openperf:fix-exec-node-workdir

Conversation

@openperf
Copy link
Copy Markdown
Member

Summary

  • Problem: When executing remote commands with host=node in a multi-user setup (e.g., Linux gateway to macOS node), the execution fails with exec INVALID_REQUEST: SYSTEM_RUN_DENIED: approval requires canonical cwd (no symlink cwd). This happens even if the working directory on the node is a valid absolute path. The issue originates in src/agents/bash-tools.exec.ts around line 361.
  • Root Cause: The gateway incorrectly applies resolveWorkdir() to the host=node request. resolveWorkdir() uses fs.statSync() to verify if the directory exists on the local gateway filesystem. Since the remote node's path (e.g., /Users/vv) doesn't exist on the Linux gateway, it falls back to the gateway's local process.cwd() or homedir(). This incorrect fallback path is then sent to the remote node, which subsequently fails the strict resolveCanonicalApprovalCwdSync checks during the approval phase on the node side.
  • Fix: Modified the else branch in src/agents/bash-tools.exec.ts to else if (host !== "node"). This prevents the gateway from attempting to resolve and validate the working directory locally when the target host is a remote node. The node is now responsible for resolving and validating its own cwd, which is the correct architectural behavior. This fix completely avoids side effects because it only changes the behavior for host=node, leaving host=gateway and host=sandbox paths untouched.
  • What changed:
    • src/agents/bash-tools.exec.ts: Added if (host !== "node") condition before calling resolveWorkdir(rawWorkdir, warnings).
  • What did NOT change (scope boundary):
    • No changes were made to how host=gateway or host=sandbox resolve their working directories.
    • No changes were made to the node-side approval logic (resolveCanonicalApprovalCwdSync); the strict security checks on the node remain fully intact.

Reproduction

  1. Setup an OpenClaw architecture with a Linux Gateway and a macOS Node.
  2. Connect the macOS node to the gateway.
  3. Run a command targeting the node: openclaw nodes run --node --cwd /Users/username -- /usr/bin/pwd
  4. Before this PR, it fails with the canonical cwd error. With this PR, it executes successfully and returns the correct path.

Risk / Mitigation

  • Risk: Low. The change is highly localized to the host=node condition in the exec tool.
  • Mitigation: The strict canonical cwd checks on the node side (src/node-host/invoke-system-run-plan.ts) are left untouched, ensuring that security boundaries are maintained at the execution endpoint. The change simply ensures the correct path is passed to those checks.

Change Type (select all)

  • Bug fix

Scope (select all touched areas)

  • Gateway / orchestration

Linked Issue/PR

Fixes #50783

AI-Assisted Contribution

  • AI Usage: This PR was developed with AI assistance.
  • Human Review: I have personally reviewed, designed, and fully understand all the code changes.
  • Testing: Fully tested locally with my OpenClaw instance.

@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: XS labels Mar 20, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 20, 2026

Greptile Summary

This PR fixes a cross-platform remote execution failure where the gateway was incorrectly using resolveWorkdir() — which calls fs.statSync() against the gateway's local filesystem — to validate a working directory that only exists on a remote node. The gateway-side stat failure caused a silent fallback to the gateway's own process.cwd(), and that wrong path was then rejected by the node's strict resolveCanonicalApprovalCwdSync checks.

The one-line fix (elseelse if (host !== "node")) is well-scoped and architecturally correct: it leaves workdir as the raw user-supplied value and lets the node validate its own cwd, which is already how the security boundaries are designed to work. The host=gateway and host=sandbox code paths are untouched.

Key observations:

  • The logic change is correct and minimal; no behavioral regression for non-node hosts.
  • The project guidelines (CLAUDE.md) recommend brief inline comments for non-obvious logic; a comment is missing here, though an identical pattern with an explanatory comment exists nearby (lines 392–393 for pathPrepend).
  • No unit tests are added or exist for this execution path; the project targets 70% coverage and prefers narrowly scoped tests for touched behavior.
  • No changelog entry is present; given this is a user-facing bug fix, an entry under ### Fixes in the active version block would be appropriate.

Confidence Score: 4/5

  • Safe to merge — the fix is minimal, well-contained to the host=node branch, and leaves all existing security checks on the node side intact.
  • The one-line change correctly addresses the root cause (gateway-side statSync fallback polluting the remote cwd). It only affects the host=node path, has no impact on gateway or sandbox execution, and the node's approval/canonical-cwd checks remain untouched. The main gaps are the absence of a test for this new branch and a missing inline comment, neither of which affect correctness.
  • No files require special attention beyond the suggestion to add an inline comment and a scoped test.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/agents/bash-tools.exec.ts
Line: 360-362

Comment:
**Missing inline comment for non-obvious branch**

The surrounding codebase consistently adds a brief comment before analogous `host === "node"` guard conditions — for example, lines 392–393 explain why `pathPrepend` is skipped for node hosts. This `else if (host !== "node")` change is equally non-obvious (why skip `resolveWorkdir` for nodes?) and would benefit from the same treatment to aid future readers without requiring them to trace the bug report.

```suggestion
      } else if (host !== "node") {
        // Skip local workdir resolution for remote node execution: the remote node's
        // filesystem is not visible to the gateway, so resolveWorkdir() would incorrectly
        // fall back to the gateway's cwd. The node is responsible for validating its own cwd.
        workdir = resolveWorkdir(rawWorkdir, warnings);
      }
```

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

Last reviewed commit: "fix(gateway): skip l..."

Comment thread src/agents/bash-tools.exec.ts
@obviyus obviyus force-pushed the fix-exec-node-workdir branch from 1abee5d to 116258b Compare March 29, 2026 12:16
Copy link
Copy Markdown
Contributor

@obviyus obviyus left a comment

Choose a reason for hiding this comment

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

Reviewed latest changes; landing now.

@obviyus obviyus merged commit fc3f6fa into openclaw:main Mar 29, 2026
18 of 20 checks passed
@obviyus
Copy link
Copy Markdown
Contributor

obviyus commented Mar 29, 2026

Landed on main.

Thanks @openperf.

Alix-007 pushed a commit to Alix-007/openclaw that referenced this pull request Mar 30, 2026
…openperf)

* fix(gateway): skip local workdir resolution for remote node execution

* chore: add inline comment for non-obvious node workdir skip

* fix: preserve node exec cwd on remote hosts (openclaw#50961) (thanks @openperf)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
alexjiang1 pushed a commit to alexjiang1/openclaw that referenced this pull request Mar 31, 2026
…openperf)

* fix(gateway): skip local workdir resolution for remote node execution

* chore: add inline comment for non-obvious node workdir skip

* fix: preserve node exec cwd on remote hosts (openclaw#50961) (thanks @openperf)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
pgondhi987 pushed a commit to pgondhi987/openclaw that referenced this pull request Mar 31, 2026
…openperf)

* fix(gateway): skip local workdir resolution for remote node execution

* chore: add inline comment for non-obvious node workdir skip

* fix: preserve node exec cwd on remote hosts (openclaw#50961) (thanks @openperf)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
…openperf)

* fix(gateway): skip local workdir resolution for remote node execution

* chore: add inline comment for non-obvious node workdir skip

* fix: preserve node exec cwd on remote hosts (openclaw#50961) (thanks @openperf)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
Tardisyuan pushed a commit to Tardisyuan/openclaw that referenced this pull request Apr 30, 2026
…openperf)

* fix(gateway): skip local workdir resolution for remote node execution

* chore: add inline comment for non-obvious node workdir skip

* fix: preserve node exec cwd on remote hosts (openclaw#50961) (thanks @openperf)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
…openperf)

* fix(gateway): skip local workdir resolution for remote node execution

* chore: add inline comment for non-obvious node workdir skip

* fix: preserve node exec cwd on remote hosts (openclaw#50961) (thanks @openperf)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
…openperf)

* fix(gateway): skip local workdir resolution for remote node execution

* chore: add inline comment for non-obvious node workdir skip

* fix: preserve node exec cwd on remote hosts (openclaw#50961) (thanks @openperf)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
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: XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: exec host=node fails with "approval requires canonical cwd (no symlink cwd)" in Linux gateway → macOS node setup

2 participants