mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 17:18:25 +00:00
fix(node-host): enforce system.run rawCommand/argv consistency
This commit is contained in:
@@ -31,6 +31,7 @@ import {
|
||||
type ExecHostResponse,
|
||||
type ExecHostRunResult,
|
||||
} from "../infra/exec-host.js";
|
||||
import { validateSystemRunCommandConsistency } from "../infra/system-run-command.js";
|
||||
import { runBrowserProxyCommand } from "./invoke-browser.js";
|
||||
|
||||
const OUTPUT_CAP = 200_000;
|
||||
@@ -174,22 +175,6 @@ function sanitizeEnv(
|
||||
return merged;
|
||||
}
|
||||
|
||||
function formatCommand(argv: string[]): string {
|
||||
return argv
|
||||
.map((arg) => {
|
||||
const trimmed = arg.trim();
|
||||
if (!trimmed) {
|
||||
return '""';
|
||||
}
|
||||
const needsQuotes = /\s|"/.test(trimmed);
|
||||
if (!needsQuotes) {
|
||||
return trimmed;
|
||||
}
|
||||
return `"${trimmed.replace(/"/g, '\\"')}"`;
|
||||
})
|
||||
.join(" ");
|
||||
}
|
||||
|
||||
function truncateOutput(raw: string, maxChars: number): { text: string; truncated: boolean } {
|
||||
if (raw.length <= maxChars) {
|
||||
return { text: raw, truncated: false };
|
||||
@@ -514,7 +499,20 @@ export async function handleInvoke(
|
||||
|
||||
const argv = params.command.map((item) => String(item));
|
||||
const rawCommand = typeof params.rawCommand === "string" ? params.rawCommand.trim() : "";
|
||||
const cmdText = rawCommand || formatCommand(argv);
|
||||
const consistency = validateSystemRunCommandConsistency({
|
||||
argv,
|
||||
rawCommand: rawCommand || null,
|
||||
});
|
||||
if (!consistency.ok) {
|
||||
await sendInvokeResult(client, frame, {
|
||||
ok: false,
|
||||
error: { code: "INVALID_REQUEST", message: consistency.message },
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const shellCommand = consistency.shellCommand;
|
||||
const cmdText = consistency.cmdText;
|
||||
const agentId = params.agentId?.trim() || undefined;
|
||||
const cfg = loadConfig();
|
||||
const agentExec = agentId ? resolveAgentConfig(cfg, agentId)?.tools?.exec : undefined;
|
||||
@@ -536,9 +534,9 @@ export async function handleInvoke(
|
||||
let allowlistMatches: ExecAllowlistEntry[] = [];
|
||||
let allowlistSatisfied = false;
|
||||
let segments: ExecCommandSegment[] = [];
|
||||
if (rawCommand) {
|
||||
if (shellCommand) {
|
||||
const allowlistEval = evaluateShellAllowlist({
|
||||
command: rawCommand,
|
||||
command: shellCommand,
|
||||
allowlist: approvals.allowlist,
|
||||
safeBins,
|
||||
cwd: params.cwd ?? undefined,
|
||||
@@ -569,7 +567,7 @@ export async function handleInvoke(
|
||||
segments = analysis.segments;
|
||||
}
|
||||
const isWindows = process.platform === "win32";
|
||||
const cmdInvocation = rawCommand
|
||||
const cmdInvocation = shellCommand
|
||||
? isCmdExeInvocation(segments[0]?.argv ?? [])
|
||||
: isCmdExeInvocation(argv);
|
||||
if (security === "allowlist" && isWindows && cmdInvocation) {
|
||||
@@ -585,7 +583,7 @@ export async function handleInvoke(
|
||||
: null;
|
||||
const execRequest: ExecHostRequest = {
|
||||
command: argv,
|
||||
rawCommand: rawCommand || null,
|
||||
rawCommand: rawCommand || shellCommand || null,
|
||||
cwd: params.cwd ?? null,
|
||||
env: params.env ?? null,
|
||||
timeoutMs: params.timeoutMs ?? null,
|
||||
@@ -780,7 +778,7 @@ export async function handleInvoke(
|
||||
security === "allowlist" &&
|
||||
isWindows &&
|
||||
!approvedByAsk &&
|
||||
rawCommand &&
|
||||
shellCommand &&
|
||||
analysisOk &&
|
||||
allowlistSatisfied &&
|
||||
segments.length === 1 &&
|
||||
|
||||
Reference in New Issue
Block a user