fix: harden exec PATH handling

This commit is contained in:
Peter Steinberger
2026-02-14 19:50:33 +01:00
parent 53af46ffb8
commit 013e8f6b3b
6 changed files with 169 additions and 51 deletions

View File

@@ -7,8 +7,11 @@ import {
type SessionNotification,
} from "@agentclientprotocol/sdk";
import { spawn, type ChildProcess } from "node:child_process";
import fs from "node:fs";
import path from "node:path";
import * as readline from "node:readline";
import { Readable, Writable } from "node:stream";
import { fileURLToPath } from "node:url";
import { ensureOpenClawCliOnPath } from "../infra/path-env.js";
import { DANGEROUS_ACP_TOOLS } from "../security/dangerous-tools.js";
@@ -260,6 +263,25 @@ function buildServerArgs(opts: AcpClientOptions): string[] {
return args;
}
function resolveSelfEntryPath(): string | null {
// Prefer a path relative to the built module location (dist/acp/client.js -> dist/entry.js).
try {
const here = fileURLToPath(import.meta.url);
const candidate = path.resolve(path.dirname(here), "..", "entry.js");
if (fs.existsSync(candidate)) {
return candidate;
}
} catch {
// ignore
}
const argv1 = process.argv[1]?.trim();
if (argv1) {
return path.isAbsolute(argv1) ? argv1 : path.resolve(process.cwd(), argv1);
}
return null;
}
function printSessionUpdate(notification: SessionNotification): void {
const update = notification.update;
if (!("sessionUpdate" in update)) {
@@ -300,13 +322,16 @@ export async function createAcpClient(opts: AcpClientOptions = {}): Promise<AcpC
const verbose = Boolean(opts.verbose);
const log = verbose ? (msg: string) => console.error(`[acp-client] ${msg}`) : () => {};
ensureOpenClawCliOnPath({ cwd });
const serverCommand = opts.serverCommand ?? "openclaw";
ensureOpenClawCliOnPath();
const serverArgs = buildServerArgs(opts);
log(`spawning: ${serverCommand} ${serverArgs.join(" ")}`);
const entryPath = resolveSelfEntryPath();
const serverCommand = opts.serverCommand ?? (entryPath ? process.execPath : "openclaw");
const effectiveArgs = opts.serverCommand || !entryPath ? serverArgs : [entryPath, ...serverArgs];
const agent = spawn(serverCommand, serverArgs, {
log(`spawning: ${serverCommand} ${effectiveArgs.join(" ")}`);
const agent = spawn(serverCommand, effectiveArgs, {
stdio: ["pipe", "pipe", "inherit"],
cwd,
});