Note: This hotfix solution is temporary and will be overwritten by official updates.
This issue was identified in version v2026.3.28, where the Gateway environment is WSL2 and the Node environment is Windows 11. These issues are likely to occur in any cross-platform environment involving Node execution.
Fix 1: Canonical CWD Validation Failure with Explicit cwd
Official Fix Available: fix(gateway): skip local workdir resolution for remote node execution by openperf · Pull Request #50961
Symptom
When running exec with host=node and the model explicitly passes a Windows-style cwd (e.g., C:\Users\xxx\.openclaw\workspace), the system returns:
SYSTEM_RUN_DENIED: approval requires an existing canonical cwdRoot Cause
Before forwarding the request to the node, the Gateway incorrectly attempts to validate or fallback the workdir using the Gateway's local filesystem (WSL). Since Windows paths are invalid/non-verifiable on WSL, the path is incorrectly modified or reset, causing the subsequent canonical check on the Node side to fail.
Critical Location: node_modules/openclaw/dist/auth-profiles-B5ypC5S-.js:43968
Solution
When host=node, skip the Gateway's local resolveWorkdir() call and preserve the original workdir string, allowing the remote Node to perform its own validation.
Code Modification (Diff)
File: auth-profiles-B5ypC5S-.js
Diff
- } else workdir = resolveWorkdir(rawWorkdir, warnings);
+ } else if (host !== "node") {
+ // Skip local workdir resolution for remote node execution...
+ workdir = resolveWorkdir(rawWorkdir, warnings);
+ }Fix 2: Validation Failure when cwd is Omitted (Gateway Path Inheritance)
Symptom
When the model does not provide a cwd, exec host=node defaults to the Gateway's current working directory (a WSL path). This path does not exist on the Windows Node, resulting in:
SYSTEM_RUN_DENIED: approval requires an existing canonical cwdRoot Cause
The default logic for rawWorkdir is defaults?.cwd || process.cwd(). While this works for Gateway-local execution, in cross-host scenarios (Gateway in WSL, Node in Windows), it sends a Linux-style path to a Windows environment.
Critical Location: node_modules/openclaw/dist/auth-profiles-B5ypC5S-.js:43957
Solution
Implement a Node Default CWD Mechanism (Per-node + Global fallback):
gateway.nodes.defaultCwdgateway.nodes.defaultCwdByNode
Logic for
host=nodewhencwdis missing:- Attempt to match
defaultCwdByNodebased on the node name. - Fallback to
defaultCwd. - If neither is defined, default to
undefined.
- Attempt to match
Logic for
host=gatewaywhencwdis missing:- Retain original behavior:
defaults?.cwd || process.cwd().
- Retain original behavior:
Code Modification (Diff)
A) Add Node Default CWD Resolution Function
Location: auth-profiles-B5ypC5S-.js:40938
Diff
return fallback;
}
+ function resolveNodeDefaultWorkdirByQuery(defaultByNode, query, fallback) {
+ const readValue = (value) => typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
+ const map = defaultByNode && typeof defaultByNode === "object" && !Array.isArray(defaultByNode) ? defaultByNode : void 0;
+ if (map && query) {
+ const direct = readValue(map[query]);
+ if (direct) return direct;
+ const lowered = query.trim().toLowerCase();
+ for (const [key, value] of Object.entries(map)) {
+ if (key.trim().toLowerCase() !== lowered) continue;
+ const match = readValue(value);
+ if (match) return match;
+ }
+ }
+ if (map) {
+ const wildcard = readValue(map["*"]) ?? readValue(map.default);
+ if (wildcard) return wildcard;
+ }
+ return readValue(fallback);
+ }
function safeCwd() ...B) Update resolveExecConfig to Pass New Config
Location: auth-profiles-B5ypC5S-.js:183481
Diff
applyPatch: ...,
+ nodeDefaultCwd: cfg?.gateway?.nodes?.defaultCwd,
+ nodeDefaultCwdByNode: cfg?.gateway?.nodes?.defaultCwdByNodeC) Inject Defaults into createExecTool
Location: auth-profiles-B5ypC5S-.js:183605
Diff
const execTool = createExecTool({
...
node: ...,
+ nodeDefaultCwd: options?.exec?.nodeDefaultCwd ?? execConfig.nodeDefaultCwd,
+ nodeDefaultCwdByNode: options?.exec?.nodeDefaultCwdByNode ?? execConfig.nodeDefaultCwdByNode,D) Modify rawWorkdir Decision Logic
Location: auth-profiles-B5ypC5S-.js:43954
Diff
- const explicitWorkdir = params.workdir?.trim();
- const rawWorkdir = host === "node" && !explicitWorkdir
- ? void 0
- : explicitWorkdir || defaults?.cwd || process.cwd();
+ const explicitWorkdir = params.workdir?.trim();
+ const nodeQuery = params.node?.trim() || defaults?.node?.trim();
+ const nodeDefaultWorkdir = host === "node" && !explicitWorkdir
+ ? resolveNodeDefaultWorkdirByQuery(defaults?.nodeDefaultCwdByNode, nodeQuery, defaults?.nodeDefaultCwd)
+ : void 0;
+ const rawWorkdir = explicitWorkdir
+ || (host === "node" ? nodeDefaultWorkdir : defaults?.cwd || process.cwd());E) Extend Configuration Schema (Avoid Unrecognized key errors)
Location: auth-profiles-B5ypC5S-.js:335532
Diff
denyCommands: z.array(z.string()).optional(),
+ defaultCwd: z.string().optional(),
+ defaultCwdByNode: z.record(z.string(), z.string()).optional()Configuration Example
Update your openclaw.json as follows:
JSON
"gateway": {
"nodes": {
"defaultCwd": "C:/Users/xxx/.openclaw/workspace",
"defaultCwdByNode": {
"win-node": "C:/Users/xxx/.openclaw/workspace",
"*": "C:/Users/xxx/.openclaw/workspace"
}
}
}Results
- Node execution with an explicit
cwdis no longer incorrectly modified by the Gateway. - Node execution with a missing
cwdno longer defaults to the Gateway's (WSL) path; it now correctly uses the configurable Windows default directory.
评论(0)