mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
fix(status): avoid false shell-wrapper audit warnings (#81778)
This commit is contained in:
@@ -28,6 +28,7 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
### Fixes
|
||||
|
||||
- **Gateway service audit:** treat POSIX shell `-c` wrappers as opaque for the gateway-subcommand check, avoiding false missing-command warnings for shell-wrapped macOS LaunchAgents without parsing inner commands or ports. Fixes #81751. (#81778) Thanks @liaoandi.
|
||||
- **Outbound channel bootstrap:** suppress repeated failed plugin activation for the same channel, config, and registry generation while retrying after config or registry reloads. (#100377) Thanks @xialonglee.
|
||||
- **OpenAI Realtime client-secret deadlines:** bound voice and transcription secret acquisition to 30 seconds through the guarded fetch boundary while preserving authentication and bounded response parsing. (#102860) Thanks @Alix-007.
|
||||
- **Gateway client watchdog:** keep transport-stall detection active for unbounded and mixed pending requests so dead sockets reject pending requests, reconnect, and never replay rejected requests. (#103407) Thanks @NianJiuZst.
|
||||
|
||||
@@ -343,6 +343,42 @@ describe("auditGatewayServiceConfig", () => {
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("treats zsh -lc LaunchAgent commands as opaque for the gateway token audit", async () => {
|
||||
const audit = await auditGatewayServiceConfig({
|
||||
env: { HOME: "/tmp" },
|
||||
platform: "darwin",
|
||||
expectedPort: 18889,
|
||||
command: {
|
||||
programArguments: [
|
||||
"/bin/zsh",
|
||||
"-lc",
|
||||
"exec /usr/bin/node /opt/openclaw/dist/index.js gateway --port 18890",
|
||||
],
|
||||
environment: {},
|
||||
},
|
||||
});
|
||||
|
||||
expect(hasIssue(audit, SERVICE_AUDIT_CODES.gatewayCommandMissing)).toBe(false);
|
||||
expect(hasIssue(audit, SERVICE_AUDIT_CODES.gatewayPortMismatch)).toBe(false);
|
||||
expect(hasIssue(audit, SERVICE_AUDIT_CODES.gatewayPathMissing)).toBe(true);
|
||||
});
|
||||
|
||||
it.each([
|
||||
["non-shell command", ["/usr/local/bin/helper", "-lc", "exec node gateway"]],
|
||||
["shell without an inline-command flag", ["/bin/zsh", "-l", "exec node gateway"]],
|
||||
])("keeps exact gateway token audit for %s", async (_name, programArguments) => {
|
||||
const audit = await auditGatewayServiceConfig({
|
||||
env: { HOME: "/tmp" },
|
||||
platform: "darwin",
|
||||
command: {
|
||||
programArguments,
|
||||
environment: {},
|
||||
},
|
||||
});
|
||||
|
||||
expect(hasIssue(audit, SERVICE_AUDIT_CODES.gatewayCommandMissing)).toBe(true);
|
||||
});
|
||||
|
||||
it("flags gateway service port drift from the expected config port", async () => {
|
||||
const audit = await auditGatewayServiceConfig({
|
||||
env: { HOME: "/tmp" },
|
||||
|
||||
@@ -10,6 +10,8 @@ import {
|
||||
sortUniqueStrings,
|
||||
} from "@openclaw/normalization-core/string-normalization";
|
||||
import { normalizeEnvVarKey } from "../infra/host-env-security.js";
|
||||
import { resolveInlineCommandMatch } from "../infra/shell-inline-command.js";
|
||||
import { POSIX_SHELL_WRAPPERS } from "../infra/shell-wrapper-resolution.js";
|
||||
import { parseTcpPort } from "../infra/tcp-port.js";
|
||||
import { VERSION } from "../version.js";
|
||||
import { resolveLaunchAgentPlistPath } from "./launchd.js";
|
||||
@@ -87,6 +89,22 @@ function hasGatewaySubcommand(programArguments?: string[]): boolean {
|
||||
return Boolean(programArguments?.some((arg) => arg === "gateway"));
|
||||
}
|
||||
|
||||
const POSIX_SERVICE_INLINE_COMMAND_FLAGS = new Set(["-c"]);
|
||||
const POSIX_SERVICE_SHELL_WRAPPERS: ReadonlySet<string> = POSIX_SHELL_WRAPPERS;
|
||||
|
||||
function isOpaquePosixShellInlineCommand(programArguments: string[]): boolean {
|
||||
const executable = programArguments[0]?.trim();
|
||||
const shellName = executable ? path.posix.basename(executable).toLowerCase() : "";
|
||||
if (!POSIX_SERVICE_SHELL_WRAPPERS.has(shellName)) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
resolveInlineCommandMatch(programArguments, POSIX_SERVICE_INLINE_COMMAND_FLAGS, {
|
||||
allowCombinedC: true,
|
||||
}).command !== null
|
||||
);
|
||||
}
|
||||
|
||||
function parseSystemdUnit(content: string): {
|
||||
after: Set<string>;
|
||||
wants: Set<string>;
|
||||
@@ -249,7 +267,10 @@ function auditGatewayCommand(programArguments: string[] | undefined, issues: Ser
|
||||
if (!programArguments || programArguments.length === 0) {
|
||||
return;
|
||||
}
|
||||
if (!hasGatewaySubcommand(programArguments)) {
|
||||
if (
|
||||
!hasGatewaySubcommand(programArguments) &&
|
||||
!isOpaquePosixShellInlineCommand(programArguments)
|
||||
) {
|
||||
issues.push({
|
||||
code: SERVICE_AUDIT_CODES.gatewayCommandMissing,
|
||||
message: "Service command does not include the gateway subcommand",
|
||||
|
||||
Reference in New Issue
Block a user