Skip to content

fix(exec): prevent shell startup files from overriding daemon env#40200

Closed
NewdlDewdl wants to merge 3 commits intoopenclaw:mainfrom
NewdlDewdl:fix/issue-40179-exec-launchd-env
Closed

fix(exec): prevent shell startup files from overriding daemon env#40200
NewdlDewdl wants to merge 3 commits intoopenclaw:mainfrom
NewdlDewdl:fix/issue-40179-exec-launchd-env

Conversation

@NewdlDewdl
Copy link
Copy Markdown
Contributor

Summary

  • run zsh exec commands with -f -c so .zshenv does not override inherited daemon environment variables
  • run bash exec commands with --noprofile --norc -c for the same deterministic env behavior
  • keep existing shell selection logic (including fish fallback), but derive args from shell type

Why

Issue #40179 reports exec commands seeing stale values despite launchd showing updated service env. Startup files can override inherited env values, causing this mismatch.

Testing

  • bash skills/openclaw-autonomous-contributor/scripts/quality_gate.sh /tmp/openclaw-issue-40179-1772997941

AI disclosure

This PR was prepared with AI assistance.

Fixes #40179

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

greptile-apps Bot commented Mar 8, 2026

Greptile Summary

This PR fixes issue #40179 by preventing shell startup files from overriding daemon-inherited environment variables during exec command execution. It adds a new helper resolvePosixShellArgs that selects shell-specific flags (zsh -f -c, bash --noprofile --norc -c, all others -c) and wires them through every branch of getShellConfig.

Key changes:

  • New resolvePosixShellArgs(shellPath) function that maps shell name to the appropriate startup-suppression flags
  • All getShellConfig return paths now call this helper instead of hardcoding ["-c"]
  • Tests extended to assert the correct args for each shell branch (bash, sh, zsh, fish fallback, unset SHELL)

Observation:

  • Fish shell (--no-config) is intentionally omitted from the startup-suppression logic per the PR description. When fish is the only available shell and is used as the final fallback, ~/.config/fish/config.fish can still override the inherited daemon environment. If this edge case matters, adding "fish" to resolvePosixShellArgs with ["--no-config", "-c"] would close the gap.

Confidence Score: 4/5

  • This PR is safe to merge; the changes are narrowly scoped and the fix is technically correct.
  • The implementation correctly uses -f for zsh (suppresses all startup files, equivalent to --no-rcs) and --noprofile --norc for bash, which are the standard flags for deterministic non-interactive invocations. Tests cover the new behavior across all relevant branches. The only intentional omission is fish's --no-config, which is a known, documented trade-off in the PR rather than an oversight.
  • No files require special attention; src/agents/shell-utils.ts is the only changed production file and the diff is small and well-tested.

Last reviewed commit: acb1b7b

Comment thread src/agents/shell-utils.ts
@NewdlDewdl
Copy link
Copy Markdown
Contributor Author

NewdlDewdl commented Mar 8, 2026

Addressed the fish fallback gap noted in feedback.

Changes pushed to fix/issue-40179-exec-launchd-env:

  • resolvePosixShellArgs now returns ["--no-config", "-c"] for fish.
  • Updated the fish fallback test in src/agents/shell-utils.test.ts to assert the new args.

Validation run locally on this branch:

  • pnpm build
  • pnpm format:check
  • pnpm tsgo
  • pnpm lint
  • pnpm test

@NewdlDewdl
Copy link
Copy Markdown
Contributor Author

Investigated the failing macOS job.

This branch is 6,973 commits behind origin/main and the failure burst is repo-wide, not in the shell-utils diff from this PR. The job is failing across unrelated suites (memory, outbound channels, ACP, Slack/Telegram/Discord, etc.), so I’m not going to push a speculative change here and pretend it fixes the PR.

Current blocker:

  • stale branch / unrelated CI avalanche
  • touched files in this PR: src/agents/shell-utils.ts, src/agents/shell-utils.test.ts
  • failing areas are far outside that scope

Recommended next step: rebase this branch onto current main (or recreate it from fresh main) and rerun CI. That should tell us whether there is still a real shell-utils regression to fix.

@NewdlDewdl NewdlDewdl force-pushed the fix/issue-40179-exec-launchd-env branch from b831c7b to ed4e1d9 Compare April 2, 2026 17:45
@openclaw-barnacle openclaw-barnacle Bot added channel: telegram Channel integration: telegram size: S and removed size: XS labels Apr 2, 2026
@NewdlDewdl NewdlDewdl force-pushed the fix/issue-40179-exec-launchd-env branch from afe0dc8 to 7fcb367 Compare April 2, 2026 21:41
@openclaw-barnacle openclaw-barnacle Bot added size: XS and removed channel: telegram Channel integration: telegram size: S labels Apr 2, 2026
@NewdlDewdl NewdlDewdl force-pushed the fix/issue-40179-exec-launchd-env branch from 7fcb367 to 8d1841b Compare April 22, 2026 09:43
@NewdlDewdl
Copy link
Copy Markdown
Contributor Author

Contributor cycle update:\n\n- Rebased onto current and resolved the merge conflict in .\n- Verified PR scope is still limited to:\n - \n - \n- Verified fish startup suppression is present () alongside existing zsh/bash suppression paths.\n\nCurrent head: \nChecks have restarted on the rebased head.

@NewdlDewdl
Copy link
Copy Markdown
Contributor Author

Correction (previous comment had shell-escaping issues):

Contributor cycle update:

  • Rebased fix/issue-40179-exec-launchd-env onto current origin/main and resolved the merge conflict in src/agents/shell-utils.ts.
  • Verified PR scope is still limited to:
    • src/agents/shell-utils.ts
    • src/agents/shell-utils.test.ts
  • Verified fish startup suppression is present (["--no-config", "-c"]) alongside existing zsh/bash suppression paths.

Current head: 8d1841b2f715f2bfc4b2ca03994baa64cc374bf5
Checks have restarted on the rebased head.

Copy link
Copy Markdown

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

Choose a reason for hiding this comment

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

💡 Codex Review

const envShell = rawEnvShell && !isNonInteractiveShell(rawEnvShell) ? rawEnvShell : undefined;

P1 Badge Restore non-interactive shell predicate before using it

getShellConfig still calls isNonInteractiveShell, but this commit removed that helper from the module. On non-Windows exec paths this becomes a ReferenceError when shell config is resolved (and the same missing symbol is referenced again in detectRuntimeShell), so command execution can fail before launching any child process unless a separate typecheck gate blocks the build.

ℹ️ 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 src/agents/shell-utils.ts Outdated
@clawsweeper
Copy link
Copy Markdown
Contributor

clawsweeper Bot commented Apr 26, 2026

Codex automated review: keeping this open.

Keep #40200 open. Current main has related PATH/login-shell handling for host exec, and #40179 was closed after a Codex review, but main still does not implement this PR's requested command-shell startup suppression for zsh, bash, or fish. The PR remains a plausible focused fix for exec commands whose invoked shell startup files override the sanitized daemon environment.

Best possible solution:

Keep the PR open for maintainer review. The best path is to rebase it onto current main, preserve the existing sh/bash PATH fallback and non-interactive shell placeholder handling, add/keep regression tests for zsh -f, bash --noprofile --norc, and fish --no-config, then run the changed exec/agents lanes. If maintainers decide startup files should remain allowed, that should be an explicit product/security decision with docs or a narrower follow-up, not an automated close.

What I checked:

  • Current main still uses plain POSIX -c args: On current main, getShellConfig returns ["-c"] for fish fallback shells, for envShell including /bin/zsh or /bin/bash, and for the sh/bash fallback. There is no resolvePosixShellArgs helper or zsh/bash/fish startup-suppression behavior on main. (src/agents/shell-utils.ts:70, 724e92505adf)
  • Host exec uses getShellConfig for command execution: runExecProcess builds childArgv from getShellConfig(), so the shell args from shell-utils are the args used for non-PTY host exec commands. (src/agents/bash-tools.exec-runtime.ts:708, 724e92505adf)
  • PTY exec also uses getShellConfig: The process supervisor's PTY path also calls getShellConfig and passes shellArgs to createPtyAdapter, so the missing suppression affects both child and PTY command paths. (src/process/supervisor/supervisor.ts:134, 724e92505adf)
  • Current tests do not cover the PR behavior: Existing shell-utils tests mainly assert shell selection; they do not assert zsh -f, bash --noprofile --norc, or fish --no-config args, except for one placeholder-shell ["-c"] case. The PR diff adds those missing assertions. (src/agents/shell-utils.test.ts:56, 724e92505adf)
  • Related main work is PATH-specific, not command-shell startup suppression: Current main imports login-shell PATH for host=gateway and sanitizes env for that PATH probe, but the actual exec command still runs through getShellConfig. This is related to [Bug]: exec tool does not inherit gateway's environment variables (launchd) #40179 but does not replace the PR's zsh/bash/fish shell-arg change. (src/agents/bash-tools.exec.ts:1590, 724e92505adf)
  • Upstream shell behavior supports the concern: zsh documentation says user startup files such as $ZDOTDIR/.zshenv are read by default after /etc/zshenv, and the RCS option is controlled by +f/NO_RCS; fish documents --no-config as the flag to skip config files. Bash --help lists --noprofile and --norc.

Remaining risk / open question:

  • The PR likely needs a current-main rebase and targeted validation because main has since added PATH/login-shell handling around the same exec surface.
  • Before merge, maintainers should decide whether zsh -f's unavoidable /etc/zshenv behavior is acceptable and whether bash --noprofile --norc is intentionally redundant for non-interactive bash.

Codex Review notes: model gpt-5.5, reasoning high; reviewed against 724e92505adf.

@NewdlDewdl
Copy link
Copy Markdown
Contributor Author

Re-verified this against current main before acting.

What I checked:

  • Current origin/main still does not have the shell startup-suppression behavior from this PR. src/agents/shell-utils.ts still returns plain ["-c"] for env-provided zsh/bash/fish paths, while this PR keeps the change scoped to src/agents/shell-utils.ts and src/agents/shell-utils.test.ts.
  • I rebased the PR branch locally onto current origin/main in a clean worktree. The rebase itself was clean.
  • I then ran the full local gate on the rebased tree: pnpm build, pnpm tsgo, and pnpm lint passed; pnpm test failed.
  • The failing tests were outside this PR scope:
    • src/agents/skills.sherpa-onnx-tts-bin.test.ts
    • src/cli/gateway-cli/run.option-collisions.test.ts
  • I reproduced those same two failures on a separate clean origin/main worktree, so this is current-main baseline red, not a shell-utils regression from this PR.

I did not force-push the rebased branch because that would rewrite the PR while the unrelated current-main test failures are still present. Once baseline is green again, this still looks like a focused fix worth rebasing and pushing cleanly.

@openclaw-clownfish
Copy link
Copy Markdown
Contributor

ProjectClownfish could not safely update this branch, so it opened a narrow replacement PR instead.

Replacement PR: #73969
Source PR: #40200
Contributor credit is preserved in the replacement PR body and changelog plan.

vincentkoc pushed a commit that referenced this pull request Apr 29, 2026
Carries forward the focused shell startup suppression fix from #40200 by NewdlDewdl.

- launch bash, zsh, and fish exec shells with startup files suppressed
- preserve fish/bash/sh PATH fallback, non-interactive shell fallback, and Windows PowerShell behavior
- add regression coverage for the affected shell arg paths

Fixes #40179.
Carries forward #40200.
Thanks @NewdlDewdl.
@vincentkoc
Copy link
Copy Markdown
Member

Thanks @NewdlDewdl. The focused startup-file suppression fix from this PR has landed via the replacement PR #73969 in ea9f172, with the contributor credit preserved in the changelog.

lxe pushed a commit to lxe/openclaw that referenced this pull request May 6, 2026
Carries forward the focused shell startup suppression fix from openclaw#40200 by NewdlDewdl.

- launch bash, zsh, and fish exec shells with startup files suppressed
- preserve fish/bash/sh PATH fallback, non-interactive shell fallback, and Windows PowerShell behavior
- add regression coverage for the affected shell arg paths

Fixes openclaw#40179.
Carries forward openclaw#40200.
Thanks @NewdlDewdl.
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
Carries forward the focused shell startup suppression fix from openclaw#40200 by NewdlDewdl.

- launch bash, zsh, and fish exec shells with startup files suppressed
- preserve fish/bash/sh PATH fallback, non-interactive shell fallback, and Windows PowerShell behavior
- add regression coverage for the affected shell arg paths

Fixes openclaw#40179.
Carries forward openclaw#40200.
Thanks @NewdlDewdl.
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 tool does not inherit gateway's environment variables (launchd)

2 participants