fix: exec workdir with leading ~ falls back and still executes command#94447
fix: exec workdir with leading ~ falls back and still executes command#94447sunlit-deng wants to merge 1 commit into
Conversation
|
Thanks for the context here. I swept through the related work, and this is now duplicate or superseded. Close: a viable sibling PR now owns the same exec workdir bug with the safer OS-home semantics and regression coverage, while this branch still has the earlier Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Canonical path: Close this duplicate PR and use #94449 as the canonical landing path for #94434. So I’m closing this here and keeping the remaining discussion on #94449 and #94434. Review detailsBest possible solution: Close this duplicate PR and use #94449 as the canonical landing path for #94434. Do we have a high-confidence way to reproduce the issue? Yes. Source inspection shows local gateway exec reaches Is this the best way to solve the issue? No. This branch is not the best remaining landing path because it uses the effective OpenClaw home, while #94449 already applies OS-home semantics with regression coverage. Security review: Security review cleared: No supply-chain, permissions, secrets, or security-boundary regression was found; the blocker is functional cwd compatibility and duplicate landing path selection. AGENTS.md: found and applied where relevant. What I checked:
Likely related people:
Codex review notes: model internal, reasoning high; reviewed against b073d7cc11dc. |
6cd8c47 to
ee3cee7
Compare
|
ClawSweeper applied the proposed close for this PR.
|
Summary
Fixes #94434
exectool'sresolveWorkdir()now expands leading~in workdir paths before stat resolutionexpandHomePrefix()utility fromsrc/infra/home-dir.tsLinked context
Real behavior proof (required for external PRs)
Behavior addressed:
resolveWorkdir()now expands leading~(tilde) in the workdir argument via the existingexpandHomePrefix()utility before callingstatSync(). Previously, a literal~was passed tostatSync(), which Node.js does not expand, causingENOENTand a silent fallback to the current working directory. Relative commands like./scripts/run.pywould then execute from the wrong directory.Real setup tested:
node --import tsx)/home/0668000974/workspace/openclaw-worktrees/issue-94434/home/0668000974Exact steps or command run after fix:
After-fix evidence:
Observed result after the fix:
~/resolves to/home/0668000974/with no warnings (previously would have silently fallen back to CWD).~/nonexistent_dir_xyz123triggers the fallback to CWD with a warning message, preserving the existing safety behavior./tmp(non-tilde path) works identically to before — no regression. Relative commands like./scripts/run.pywill now execute from the correct expanded directory instead of the fallback directory.What was not tested: Full gateway end-to-end with live model emitting
workdir: "~..."tool calls — blocked by a pre-existing@pierre/diffsbuild dependency issue in this worktree that is unrelated to this change. The function-level verification above directly tests the changed code path. Sandbox workdir path (uses separate resolver, not affected).Proof limitations or environment constraints: The
@pierre/diffsbuild dependency is missing in this worktree, preventing a fullpnpm openclaw exectest. However, the fix is purely inresolveWorkdir()which is tested directly above. The existingexpandHomePrefix()utility has 27 passing unit tests insrc/infra/home-dir.test.ts.Tests and validation
src/infra/home-dir.test.ts: 27/27 tests passed — expandHomePrefix is already well-coveredpnpm check: All guards passed; only pre-existingnpm shrinkwrap guardfailure (unrelated)How I know the risk surface is small
The change introduces no new algorithms, dependencies, or file I/O. It calls an existing utility that is already in production use (via
executable-path.tsfor the same purpose — expanding~in user-supplied paths). The edit touches 3 lines in a single file:expandHomePrefixfrom a sibling moduleconst expanded = expandHomePrefix(workdir)— one new linestatSync(expanded)instead ofstatSync(workdir)— one variable reference changeexpandedinstead ofworkdir— correct, consumers should receive the resolved pathPaths that do not start with
~pass throughexpandHomePrefix()unchanged (identity return on line 99 of home-dir.ts). The fallback path is unmodified.Boundary cases
expandHomePrefixonly matches leading~followed by end-of-string or path separator.$HOME,${HOME}, wildcards, etc. are not expanded. This is consistent with the issue reporter's request.~user/other? No. The regex/^~(?=$|[\\/])/only matches bare~. Structured tool arguments should not perform user-lookup expansion.resolveWorkdiroverride (seesandbox/backend.test.ts:49), not this function. The change is scoped to host-side exec.OPENCLAW_HOME?expandHomePrefixhonorsOPENCLAW_HOMEenv var, consistent with all other path resolution in the codebase.statSyncresolves real paths through the OS as before, no change.Risk checklist
Did user-visible behavior change? (
Yes/No)Yes— exec calls withworkdir: "~..."now run from the expanded directory instead of silently falling back to CWD.Did config, environment, or migration behavior change? (
Yes/No)No— no new config keys, no migration scripts, no environment variable changes.Did security, auth, secrets, network, or tool execution behavior change? (
Yes/No)No— only local path expansion before stat check. No network, auth, or tool execution changes.What is the highest-risk area?
~paths will now execute from the expanded directory. This is the intended fix, but it is a behavior change.How is that risk mitigated?
~expansion will behave differently. This is universally an improvement — the prior behavior was a bug, not a feature.Current review state
What is the next action?
What is still waiting on author, maintainer, CI, or external proof?
Which bot or reviewer comments were addressed?