Skip to content

fix(exec): protect pathPrepend against posix login-shell RC overrides#81403

Merged
odysseus0 merged 3 commits into
openclaw:mainfrom
medns:fix/exec-pathPrepend-priority
May 21, 2026
Merged

fix(exec): protect pathPrepend against posix login-shell RC overrides#81403
odysseus0 merged 3 commits into
openclaw:mainfrom
medns:fix/exec-pathPrepend-priority

Conversation

@medns

@medns medns commented May 13, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Problem: In POSIX environments, tools.exec.pathPrepend entries can be unexpectedly overridden or pushed down the priority list by user login-shell configuration files (like ~/.zshenv or /etc/zshenv) during shell startup.
  • Why it matters: The pathPrepend config is intended to guarantee that specific tools (like config/bin or user-defined overrides) take absolute precedence during execution, but RC file execution defeats this guarantee.
  • What changed: Relies on the shell to expand OPENCLAW_PREPEND_PATH natively into the PATH right before the target command executes (export PATH="${OPENCLAW_PREPEND_PATH}:$PATH"; unset OPENCLAW_PREPEND_PATH; <command>).
  • What did NOT change (scope boundary): Windows behavior remains untouched since it does not suffer from POSIX RC file overriding mechanisms.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #
  • Related #
  • This PR fixes a bug or regression

Real behavior proof (required for external PRs)

  • Behavior or issue addressed: Ensure tools.exec.pathPrepend works reliably regardless of user ~/.zshenv setups.
  • Real environment tested: macOS host running OpenClaw Gateway with a modified ~/.zshenv
  • Exact steps or command run after this patch:
    1. Configured tools.exec.pathPrepend to ["/custom/bin"].
    2. Modified ~/.zshenv to contain export PATH="/evil/bin:$PATH".
    3. Ran /exec host=gateway and then echo $PATH in an OpenClaw Chat.
  • Evidence after fix:
    Terminal output of the executed command inside the OpenClaw environment:
    $ openclaw chat
    > /exec host=gateway
    > echo $PATH
    /custom/bin:/evil/bin:/usr/bin:/bin
    
  • Observed result after fix: The output proves that the configured prepend /custom/bin takes absolute priority over the RC file injection /evil/bin, bypassing the host shell tampering.
  • What was not tested: Windows host RC files (not applicable).

Copilot AI review requested due to automatic review settings May 13, 2026 12:42
@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation agents Agent runtime and tooling size: M triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI. labels May 13, 2026
@medns medns changed the title fix(exec): protect pathPrepend against posix login-shell RC overrides WIP(exec): protect pathPrepend against posix login-shell RC overrides May 13, 2026
@clawsweeper

clawsweeper Bot commented May 13, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs changes before merge.

Workflow note: Future ClawSweeper reviews update this same comment in place.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

Summary
The PR threads tools.exec.pathPrepend into gateway host exec and wraps POSIX commands with a shell-time PATH export via OPENCLAW_PREPEND_PATH, plus tests, docs, and a changelog entry.

Reproducibility: yes. source inspection gives a high-confidence reproduction path: current main applies pathPrepend to the environment before launching the shell, while POSIX startup files can prepend to PATH before -c command execution. I did not run the live macOS ~/.zshenv repro in this read-only review.

PR rating
Overall: 🐚 platinum hermit
Proof: 🐚 platinum hermit
Patch quality: 🐚 platinum hermit
Summary: The PR has useful real-environment proof and a reasonable implementation, with only low-severity docs and whitespace cleanup remaining.

Rank-up moves:

  • Move the POSIX PATH note out from under the Linux bullet.
  • Remove the trailing whitespace and rerun git diff --check.
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Real behavior proof
Sufficient (live_output): The PR body includes copied after-fix OpenClaw chat output from a macOS gateway with a modified ~/.zshenv, and the latest head changes after that proof are test-only.

Risk before merge

  • Existing POSIX gateway configs that relied on pathPrepend entries being visible to shell startup files before command execution may see different startup behavior after this change.
  • The diff changes host exec shell command construction and command-resolution PATH order, so maintainers should treat it as security-boundary-sensitive even though no concrete security defect was found.
  • This read-only review did not run the focused Vitest files or a broad changed gate; git diff --check was the only executed validation command and it currently fails.

Maintainer options:

  1. Fix cleanup before merge (recommended)
    Remove the trailing whitespace and move the POSIX docs note out from under the Linux bullet, then rerun whitespace and focused exec path checks.
  2. Ask for a fresh live gateway smoke
    A maintainer can require a fresh macOS or Linux gateway run at the current head if they want live proof after the final force-push, even though the latest commits only changed tests.
  3. Accept the startup-file visibility change
    Maintainers may explicitly accept that configured pathPrepend entries are enforced after shell startup and are no longer guaranteed to be visible to startup files themselves.
Copy recommended automerge instruction
@clawsweeper automerge

Special instructions:
Remove the trailing whitespace in src/agents/bash-tools.exec-runtime.ts and move the POSIX pathPrepend note out from under the Linux bullet in docs/tools/exec.md so it applies to host=gateway generally; then run git diff --check and the focused exec path tests.

Next step before merge
A narrow automated repair can fix the docs indentation and trailing whitespace; runtime merge still needs normal maintainer acceptance of the exec PATH boundary.

Security
Cleared: The diff touches shell command execution, but the configured paths are passed through an environment variable and no concrete secret, permission, dependency, CI, or supply-chain regression was found.

Review findings

  • [P3] Move the PATH note out from under Linux — docs/tools/exec.md:136
  • [P3] Remove the trailing whitespace — src/agents/bash-tools.exec-runtime.ts:797
Review details

Best possible solution:

Land the shell-time PATH prepend approach after the docs and whitespace cleanup, with maintainer acceptance that pathPrepend is enforced at command time rather than startup-file time.

Do we have a high-confidence way to reproduce the issue?

Yes, source inspection gives a high-confidence reproduction path: current main applies pathPrepend to the environment before launching the shell, while POSIX startup files can prepend to PATH before -c command execution. I did not run the live macOS ~/.zshenv repro in this read-only review.

Is this the best way to solve the issue?

Yes with cleanup: applying the prepend inside the shell command via an environment variable is the right runtime boundary for this bug. The remaining fixes are docs placement and whitespace validation, not a different product design.

Label changes:

  • add P2: This is a normal-priority exec bug fix with limited blast radius but real command-resolution impact for configured gateway PATH prepends.
  • add merge-risk: 🚨 compatibility: Merging changes when POSIX gateway pathPrepend entries appear relative to shell startup files, which can affect existing local shell setups.
  • add merge-risk: 🚨 security-boundary: The diff changes host exec shell command construction and PATH precedence, both part of the command-resolution security boundary.
  • add proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes copied after-fix OpenClaw chat output from a macOS gateway with a modified ~/.zshenv, and the latest head changes after that proof are test-only.
  • add rating: 🐚 platinum hermit: Current PR rating is 🐚 platinum hermit because proof is 🐚 platinum hermit, patch quality is 🐚 platinum hermit, and The PR has useful real-environment proof and a reasonable implementation, with only low-severity docs and whitespace cleanup remaining.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): The PR body includes copied after-fix OpenClaw chat output from a macOS gateway with a modified ~/.zshenv, and the latest head changes after that proof are test-only.

Label justifications:

  • P2: This is a normal-priority exec bug fix with limited blast radius but real command-resolution impact for configured gateway PATH prepends.
  • merge-risk: 🚨 compatibility: Merging changes when POSIX gateway pathPrepend entries appear relative to shell startup files, which can affect existing local shell setups.
  • merge-risk: 🚨 security-boundary: The diff changes host exec shell command construction and PATH precedence, both part of the command-resolution security boundary.
  • rating: 🐚 platinum hermit: Current PR rating is 🐚 platinum hermit because proof is 🐚 platinum hermit, patch quality is 🐚 platinum hermit, and The PR has useful real-environment proof and a reasonable implementation, with only low-severity docs and whitespace cleanup remaining.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): The PR body includes copied after-fix OpenClaw chat output from a macOS gateway with a modified ~/.zshenv, and the latest head changes after that proof are test-only.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes copied after-fix OpenClaw chat output from a macOS gateway with a modified ~/.zshenv, and the latest head changes after that proof are test-only.

Full review comments:

  • [P3] Move the PATH note out from under Linux — docs/tools/exec.md:136
    This new sentence is indented as a child of the Linux PATH bullet, so the docs read as if the protection is Linux-only. Align it with the host=gateway PATH handling text or make it a separate POSIX gateway note.
    Confidence: 0.88
  • [P3] Remove the trailing whitespace — src/agents/bash-tools.exec-runtime.ts:797
    git diff --check HEAD...918bf1395fcfe82dacb360e166254f21d6a4f755 reports trailing whitespace on this added blank line, so the branch needs that removed before normal merge checks can pass.
    Confidence: 0.96

Overall correctness: patch is correct
Overall confidence: 0.84

Acceptance criteria:

  • git diff --check
  • node scripts/run-vitest.mjs src/agents/bash-tools.test.ts src/agents/bash-tools.exec-runtime.test.ts src/infra/path-prepend.test.ts

What I checked:

Likely related people:

  • steipete: History shows Peter Steinberger introduced tools.exec.pathPrepend, merged gateway login-shell PATH handling, hardened sandbox PATH injection, and later adjusted node-host pathPrepend behavior in the same exec/PATH surface. (role: feature introducer and recent area contributor; confidence: high; commits: 953472bf2513, e45228ac372c, 771f23d36b95; files: src/agents/bash-tools.exec.ts, src/agents/bash-tools.exec-runtime.ts, src/agents/bash-tools.shared.ts)
  • Takhoffman: Tak Hoffman authored the Windows PATH key case-insensitivity fix for the pathPrepend helper area, which is adjacent to this PR's PATH normalization changes. (role: adjacent pathPrepend contributor; confidence: medium; commits: 21708f58ceb0; files: src/infra/path-prepend.ts, src/agents/bash-tools.test.ts)
  • vincentkoc: Vincent Koc has recent commits in exec runtime and host approval/security paths, making him a useful adjacent reviewer for command-execution boundary changes. (role: recent exec runtime contributor; confidence: medium; commits: 87b2a6a16aa2, 5dca81271cd7, dae6632da110; files: src/agents/bash-tools.exec-runtime.ts, src/agents/bash-tools.exec.ts, src/agents/bash-tools.exec-host-gateway.ts)

Codex review notes: model gpt-5.5, reasoning high; reviewed against 016c34ff1d2a.

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

This PR aims to ensure tools.exec.pathPrepend retains highest PATH precedence on POSIX hosts even when shell startup files (e.g., ~/.zshenv) rewrite PATH, by moving the prepend enforcement into the shell command that ultimately runs.

Changes:

  • Add removePathPrepend() helper to strip existing prepended entries from a PATH string.
  • Thread pathPrepend through exec host/gateway execution and wrap POSIX commands with an export PATH=... prologue.
  • Add/update unit tests and docs describing the new precedence protection behavior.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/infra/path-prepend.ts Adds removePathPrepend() to remove configured prepends from an existing PATH string.
src/infra/path-prepend.test.ts Adds coverage for removePathPrepend() behavior (normal, tampered, duplicates, whitespace).
src/agents/bash-tools.exec.ts Threads pathPrepend into runtime/gateway execution and clears inherited OPENCLAW_PREPEND_PATH before applying prepends.
src/agents/bash-tools.exec-runtime.ts Introduces a POSIX command wrapper intended to re-prepend PATH after shell startup and strips duplicates from base env.
src/agents/bash-tools.exec-host-gateway.ts Passes pathPrepend through gateway allowlist execution into runExecProcess().
src/agents/bash-tools.exec-runtime.test.ts Adds a unit test asserting the wrapped command string contains the PATH export prologue.
src/agents/bash-tools.test.ts Adds a new PATH-handling test intended to simulate RC-file PATH overrides.
docs/tools/exec.md Documents that tools.exec.pathPrepend is applied inside the shell command to prevent RC startup overrides.

Comment thread src/agents/bash-tools.exec-runtime.ts Outdated
Comment thread src/agents/bash-tools.exec-runtime.test.ts
Comment thread src/infra/path-prepend.ts Outdated
Comment thread src/agents/bash-tools.test.ts Outdated
@openclaw-barnacle openclaw-barnacle Bot added triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. and removed triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI. labels May 13, 2026
@medns
medns force-pushed the fix/exec-pathPrepend-priority branch 3 times, most recently from 815f531 to 0989a5c Compare May 14, 2026 03:21
@openclaw-barnacle openclaw-barnacle Bot added proof: supplied External PR includes structured after-fix real behavior proof. and removed triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels May 14, 2026
@medns medns changed the title WIP(exec): protect pathPrepend against posix login-shell RC overrides fix(exec): protect pathPrepend against posix login-shell RC overrides May 14, 2026
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 14, 2026
@odysseus0
odysseus0 force-pushed the fix/exec-pathPrepend-priority branch from 0989a5c to 918bf13 Compare May 21, 2026 19:46
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 21, 2026
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. labels May 21, 2026
@clawsweeper

clawsweeper Bot commented May 21, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper PR egg

✨ Hatched: ✨ glimmer Gilded Signal Puff

Hatch command

Comment @clawsweeper hatch when this PR is hatchable.

Hatchability rules:

  • Merged PRs are hatchable.
  • Open PRs are hatchable when they are status: 👀 ready for maintainer look, status: 🚀 automerge armed, or labeled clawsweeper:automerge.
  • Closed unmerged PRs are hatchable only when one of those hatchable labels is still present in the durable record.

Rarity: ✨ glimmer.
Trait: sniffs out flaky tests.
Image traits: location CI tidepool; accessory rollback rope; palette pearl, teal, and neon green; mood mischievous; pose standing beside its cracked shell; shell soft velvet shell; lighting subtle sparkle highlights; background delicate sparkle particles.
Share on X: post this hatch
Copy: My PR egg hatched a ✨ glimmer Gilded Signal Puff in ClawSweeper.

What is this egg doing here?
  • Eggs appear after the PR passes real-behavior proof. It is here for vibes, not verdicts: it does not change labels, ratings, merge decisions, or automation.
  • The shell reacts to review momentum: open follow-up work warms it up, re-review makes it wobble, and a clean final review lets it hatch.
  • Hatchability usually comes from sufficient real-behavior proof, no blocking P0/P1/P2 findings, no security attention needed, and clean correctness. A merged PR is already final, so merge makes the egg hatchable independently.
  • The hatch is seeded from this repository and PR number, so the same PR keeps the same creature; the reviewed head SHA can only change safe visual details.
  • Rarity is just collectible sparkle: 🥚 common, 🌱 uncommon, 💎 rare, ✨ glimmer, and 🌈 legendary.

@odysseus0
odysseus0 force-pushed the fix/exec-pathPrepend-priority branch from 918bf13 to 7c79e0f Compare May 21, 2026 20:12
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 21, 2026
@odysseus0
odysseus0 force-pushed the fix/exec-pathPrepend-priority branch from 7c79e0f to 874fa90 Compare May 21, 2026 20:19
@odysseus0
odysseus0 merged commit b77f36f into openclaw:main May 21, 2026
24 checks passed
@odysseus0

Copy link
Copy Markdown
Contributor

Merged via squash.

Thanks @medns!

SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request May 24, 2026
…openclaw#81403)

Merged via squash.

Prepared head SHA: 874fa90
Co-authored-by: medns <[email protected]>
Co-authored-by: odysseus0 <[email protected]>
Reviewed-by: @odysseus0
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request May 24, 2026
…openclaw#81403)

Merged via squash.

Prepared head SHA: 874fa90
Co-authored-by: medns <[email protected]>
Co-authored-by: odysseus0 <[email protected]>
Reviewed-by: @odysseus0
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request May 24, 2026
…openclaw#81403)

Merged via squash.

Prepared head SHA: 874fa90
Co-authored-by: medns <[email protected]>
Co-authored-by: odysseus0 <[email protected]>
Reviewed-by: @odysseus0
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
…openclaw#81403)

Merged via squash.

Prepared head SHA: 874fa90
Co-authored-by: medns <[email protected]>
Co-authored-by: odysseus0 <[email protected]>
Reviewed-by: @odysseus0
galiniliev pushed a commit to galiniliev/openclaw that referenced this pull request May 25, 2026
…openclaw#81403)

Merged via squash.

Prepared head SHA: 874fa90
Co-authored-by: medns <[email protected]>
Co-authored-by: odysseus0 <[email protected]>
Reviewed-by: @odysseus0
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request May 26, 2026
…openclaw#81403)

Merged via squash.

Prepared head SHA: 874fa90
Co-authored-by: medns <[email protected]>
Co-authored-by: odysseus0 <[email protected]>
Reviewed-by: @odysseus0
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request May 26, 2026
…openclaw#81403)

Merged via squash.

Prepared head SHA: 874fa90
Co-authored-by: medns <[email protected]>
Co-authored-by: odysseus0 <[email protected]>
Reviewed-by: @odysseus0
SebTardif pushed a commit to SebTardif/openclaw that referenced this pull request May 26, 2026
…openclaw#81403)

Merged via squash.

Prepared head SHA: 874fa90
Co-authored-by: medns <[email protected]>
Co-authored-by: odysseus0 <[email protected]>
Reviewed-by: @odysseus0
jameslcowan pushed a commit to jameslcowan/openclaw that referenced this pull request Jun 2, 2026
…openclaw#81403)

Merged via squash.

Prepared head SHA: 874fa90
Co-authored-by: medns <[email protected]>
Co-authored-by: odysseus0 <[email protected]>
Reviewed-by: @odysseus0
SYU8384 pushed a commit to SYU8384/openclaw that referenced this pull request Jun 3, 2026
…openclaw#81403)

Merged via squash.

Prepared head SHA: 874fa90
Co-authored-by: medns <[email protected]>
Co-authored-by: odysseus0 <[email protected]>
Reviewed-by: @odysseus0
sablehead pushed a commit to sablehead/openclaw that referenced this pull request Jun 10, 2026
…openclaw#81403)

Merged via squash.

Prepared head SHA: 874fa90
Co-authored-by: medns <[email protected]>
Co-authored-by: odysseus0 <[email protected]>
Reviewed-by: @odysseus0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling docs Improvements or additions to documentation merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. P2 Normal backlog priority with limited blast radius. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: M status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants