Skip to content

fix(daemon): recognize shell-wrapped gateway commands in service audit#81755

Closed
Bartok9 wants to merge 1 commit into
openclaw:mainfrom
Bartok9:fix/81751-service-audit-shell-wrap-gateway-check
Closed

fix(daemon): recognize shell-wrapped gateway commands in service audit#81755
Bartok9 wants to merge 1 commit into
openclaw:mainfrom
Bartok9:fix/81751-service-audit-shell-wrap-gateway-check

Conversation

@Bartok9

@Bartok9 Bartok9 commented May 14, 2026

Copy link
Copy Markdown
Contributor

Problem

When a LaunchAgent's ProgramArguments uses a shell wrapper like:

["/bin/zsh", "-lc", "set -a; ...; exec .../openclaw/dist/index.js gateway --port 18890"]

gateway status reports:

Service config issue: Service command does not include the gateway subcommand

...even though the gateway is reachable and running correctly.

Root Cause

hasGatewaySubcommand() checked if any element in programArguments exactly equals "gateway". When the gateway binary is invoked inside a shell inline command (the third array element), "gateway" is embedded in a larger string — never a standalone token.

Fix

Extended hasGatewaySubcommand with a secondary check: when programArguments[0] is a recognized POSIX shell (sh, bash, zsh, dash, fish), scan subsequent arguments for a -c/-lc/etc. flag, then test the following inline command string for /\bgateway\b/.

Tests Added

Three new cases in service-audit.test.ts:

  1. /bin/zsh -lc wrapper with gateway in the inline command → no false positive
  2. /bin/sh -c wrapper with gateway in the inline command → no false positive
  3. /bin/sh -c wrapper without gateway → correctly flags gateway-command-missing

Fixes #81751

When a LaunchAgent ProgramArguments is wrapped in a POSIX shell
invocation (`/bin/zsh -lc "... gateway --port ..."`), the service
audit incorrectly reported 'Service command does not include the gateway
subcommand' because `hasGatewaySubcommand` only checked for a bare
'gateway' token in the array, not inside shell inline-command strings.

The fix extends `hasGatewaySubcommand` to also recognise the pattern:
  ["<shell>", "-c|-lc|-...", "<inline-cmd-containing-gateway>"]

where <shell> is any common POSIX shell basename (sh, bash, zsh, dash,
fish).  A word-boundary regex test on the inline command string confirms
that 'gateway' is present as a subcommand, not as part of an unrelated
path segment.

Fixes openclaw#81751.
@openclaw-barnacle openclaw-barnacle Bot added gateway Gateway runtime size: S triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels May 14, 2026
@clawsweeper

clawsweeper Bot commented May 14, 2026

Copy link
Copy Markdown
Contributor

Thanks for the context here. I swept through the related work, and this is now duplicate or superseded.

Close as duplicate/superseded: the same shell-wrapped LaunchAgent audit bug is now covered by the canonical open PR at #81778, which updates the same service-audit surface, includes real macOS proof, and avoids this PR's broad substring bug.

Canonical path: Use #81778 as the canonical fix path, then close the linked issue after that PR lands.

So I’m closing this here and keeping the remaining discussion on the canonical linked item.

Review details

Best possible solution:

Use #81778 as the canonical fix path, then close the linked issue after that PR lands.

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

Yes. Current main passes LaunchAgent ProgramArguments into the service audit unchanged, while hasGatewaySubcommand only checks exact argv elements, so the reported /bin/zsh -lc wrapper is source-reproducible as a false gateway-command-missing issue.

Is this the best way to solve the issue?

No for this PR as the merge path. The canonical open PR is the better solution because it covers the same bug with real behavior proof, port parsing, and a near-match negative regression without broad word-boundary matching.

Security review:

Security review cleared: The diff only changes local TypeScript service-audit parsing and tests, with no dependency, workflow, secret, install, or supply-chain surface change.

What I checked:

  • Current main source behavior: Current main still only treats the gateway subcommand as present when a programArguments element exactly equals gateway, and gatherDaemonStatus passes the read service command into auditGatewayServiceConfig, so the linked shell-wrapper report is source-reproducible. (src/daemon/service-audit.ts:73, f74436dc81bc)
  • PR correctness issue: The proposed /\bgateway\b/ check accepts gateway anywhere in the inline shell string, including path or option text, so it can suppress gateway-command-missing for commands that still do not run the gateway subcommand. (src/daemon/service-audit.ts:113, 59651eef8cf2)
  • Canonical overlapping PR: fix(status): avoid false shell-wrapper audit warnings #81778 is open, non-draft, closes the same linked issue, changes the same files, adds shell-wrapper audit coverage plus a near-match negative case, and has ClawSweeper proof-sufficient review based on real macOS LaunchAgent terminal output. (src/daemon/service-audit.ts:70, 8ba8752fae98)
  • Duplicate search: A GitHub search for gateway-command-missing shows the linked issue, this PR, the canonical open PR, and a later closed duplicate PR, confirming this item is part of the same cluster rather than a unique remaining fix path.
  • Feature history: GitHub file history shows src/daemon/service-audit.ts was introduced for supervisor config auditing in 01641b34..., then tightened for service entrypoint auditing in 083877d...; recent gateway status and LaunchAgent work also touched the affected path. (src/daemon/service-audit.ts:73, 01641b34ea62)

Likely related people:

  • steipete: GitHub file history attributes the original service audit supervisor config work, the service entrypoint audit tightening, and recent status warning work to this area contributor. (role: introduced and recent area contributor; confidence: high; commits: 01641b34ea62, 083877d2867e, fea1c8e71d73; files: src/daemon/service-audit.ts, src/commands/doctor-gateway-services.ts, src/cli/daemon-cli/status.gather.ts)
  • vincentkoc: Recent gateway status work changed status.gather.ts, the caller that reads the platform service command and passes it to the audit path involved here. (role: recent status-path contributor; confidence: medium; commits: 831f03b8140f; files: src/cli/daemon-cli/status.gather.ts, src/cli/daemon-cli/status.gather.test.ts)
  • BunsDev: Recent macOS gateway LaunchAgent lifecycle work touched the launchd service surface adjacent to the reported shell-wrapped LaunchAgent behavior. (role: recent adjacent LaunchAgent contributor; confidence: medium; commits: fa79e9754ecc, b405c6e640be; files: src/daemon/launchd.ts, src/daemon/launchd.test.ts)
  • shakkernerd: Recent history shows focused coverage work in src/daemon/service-audit.test.ts, the test surface for this fix cluster. (role: recent service-audit test contributor; confidence: medium; commits: 9c3795143528; files: src/daemon/service-audit.test.ts)

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gateway Gateway runtime size: S triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

gateway status incorrectly reports LaunchAgent command missing gateway subcommand

1 participant