diff --git a/CHANGELOG.md b/CHANGELOG.md index df89f2e956e..96121d30ec8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ Docs: https://docs.openclaw.ai ### Fixes - Synology Chat/security: route webhook token comparison through the shared constant-time secret helper for consistency with other bundled plugins. +- Node exec approvals: keep node-host `system.run` approvals bound to the prepared execution plan, so script-drift revalidation still runs after agent-side approval forwarding. - Models/MiniMax: honor `MINIMAX_API_HOST` for implicit bundled MiniMax provider catalogs so China-hosted API-key setups pick `api.minimaxi.com/anthropic` without manual provider config. (#34524) Thanks @caiqinghua. - Usage/MiniMax: invert remaining-style `usage_percent` fields when MiniMax reports only remaining percentage data, so usage bars stop showing nearly-full remaining quota as nearly-exhausted usage. (#60254) Thanks @jwchmodx. - MiniMax: advertise image input on bundled `MiniMax-M2.7` and `MiniMax-M2.7-highspeed` model definitions so image-capable flows can route through the M2.7 family correctly. (#54843) Thanks @MerlinMiao88888888. diff --git a/src/agents/bash-tools.exec.approval-id.test.ts b/src/agents/bash-tools.exec.approval-id.test.ts index 81645b7d16b..f2f36812313 100644 --- a/src/agents/bash-tools.exec.approval-id.test.ts +++ b/src/agents/bash-tools.exec.approval-id.test.ts @@ -1253,6 +1253,19 @@ describe("exec approvals", () => { mockNoApprovalRouteRegistration(); let systemRunInvoke: unknown; + const preparedPlan = { + argv: ["/bin/sh", "-lc", "echo cron-node-ok"], + cwd: null, + commandText: "/bin/sh -lc 'echo cron-node-ok'", + commandPreview: "echo cron-node-ok", + agentId: null, + sessionKey: null, + mutableFileOperand: { + argvIndex: 2, + path: "/tmp/cron-node-ok.sh", + sha256: "deadbeef", + }, + }; vi.mocked(callGatewayTool).mockImplementation(async (method, _opts, params) => { if (method === "exec.approval.request") { return { id: "approval-id", decision: null }; @@ -1263,7 +1276,11 @@ describe("exec approvals", () => { if (method === "node.invoke") { const invoke = params as { command?: string }; if (invoke.command === "system.run.prepare") { - return buildPreparedSystemRunPayload(params); + return { + payload: { + plan: preparedPlan, + }, + }; } if (invoke.command === "system.run") { systemRunInvoke = params; @@ -1292,6 +1309,7 @@ describe("exec approvals", () => { params: { approved: true, approvalDecision: "allow-once", + systemRunPlan: preparedPlan, }, }); expect((systemRunInvoke as { params?: { runId?: string } }).params?.runId).toEqual(