mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 07:40:44 +00:00
fix(approvals): accept allowlist metadata
This commit is contained in:
@@ -7,6 +7,7 @@ Docs: https://docs.openclaw.ai
|
||||
### Fixes
|
||||
|
||||
- macOS Gateway: write launchd services with a state-dir `WorkingDirectory`, use a durable state-dir temp path instead of freezing macOS session `TMPDIR`, create that temp directory before bootstrap, and label abort-shaped launchd exits as `SIGABRT/abort` in status output. Fixes #53679 and #70223; refs #71848. Thanks @dlturock, @stammi922, and @palladius.
|
||||
- Exec approvals: accept runtime-owned `source: "allow-always"` and `commandText` allowlist metadata in gateway and node approval-set payloads so Control UI round-trips no longer fail with `unexpected property 'source'`. Fixes #60000; carries forward #60064. Thanks @sd1471123, @sharkqwy, and @luoyanglang.
|
||||
- Exec/node: skip approval-plan preparation for full-trust `host=node` runs so interpreter and script commands no longer fail with `SYSTEM_RUN_DENIED: approval cannot safely bind` when effective policy is `security=full` and `ask=off`. Fixes #48457 and duplicate #69251. Thanks @ajtran303, @jaserNo1, @Blakeshannon, @lesliefag, and @AvIsBeastMC.
|
||||
- Exec/node: synthesize a local approval plan when a paired node advertises `system.run` without `system.run.prepare`, unblocking approval-required `host=node` exec on current macOS companion nodes while preserving remote prepare for node hosts that support it. Fixes #37591 and duplicate #66839; carries forward #69725. Thanks @soloclz.
|
||||
- Memory/QMD: prefer QMD's `--mask` collection pattern flag so root memory indexing stays scoped to `MEMORY.md` instead of widening to every markdown file in the workspace. Thanks @codex.
|
||||
|
||||
@@ -99,6 +99,8 @@ Example schema:
|
||||
{
|
||||
"id": "B0C8C0B3-2C2D-4F8A-9A3C-5A4B3C2D1E0F",
|
||||
"pattern": "~/Projects/**/bin/rg",
|
||||
"source": "allow-always",
|
||||
"commandText": "rg -n TODO",
|
||||
"lastUsedAt": 1737150000000,
|
||||
"lastUsedCommand": "rg -n TODO",
|
||||
"lastResolvedPath": "/Users/user/Projects/.../bin/rg"
|
||||
|
||||
75
src/gateway/protocol/exec-approvals-validators.test.ts
Normal file
75
src/gateway/protocol/exec-approvals-validators.test.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { validateExecApprovalsNodeSetParams, validateExecApprovalsSetParams } from "./index.js";
|
||||
|
||||
describe("exec approvals protocol validators", () => {
|
||||
it("accepts runtime-owned allowlist metadata on gateway and node set payloads", () => {
|
||||
const file = {
|
||||
version: 1 as const,
|
||||
agents: {
|
||||
main: {
|
||||
allowlist: [
|
||||
{
|
||||
id: "entry-1",
|
||||
pattern: "cmd:allow-always:abcdef",
|
||||
source: "allow-always" as const,
|
||||
commandText: "python3 -c 'print(123)'",
|
||||
argPattern: "-c *",
|
||||
lastUsedAt: 1775154056736,
|
||||
lastUsedCommand: "python3 -c 'print(123)'",
|
||||
lastResolvedPath: "/usr/bin/python3",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
expect(validateExecApprovalsSetParams({ file, baseHash: "abc123" })).toBe(true);
|
||||
expect(
|
||||
validateExecApprovalsNodeSetParams({
|
||||
nodeId: "node-1",
|
||||
file,
|
||||
baseHash: "abc123",
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("rejects unknown allowlist metadata", () => {
|
||||
expect(
|
||||
validateExecApprovalsSetParams({
|
||||
file: {
|
||||
version: 1,
|
||||
agents: {
|
||||
main: {
|
||||
allowlist: [
|
||||
{
|
||||
pattern: "/usr/bin/python3",
|
||||
source: "unknown-source",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
baseHash: "abc123",
|
||||
}),
|
||||
).toBe(false);
|
||||
|
||||
expect(
|
||||
validateExecApprovalsSetParams({
|
||||
file: {
|
||||
version: 1,
|
||||
agents: {
|
||||
main: {
|
||||
allowlist: [
|
||||
{
|
||||
pattern: "/usr/bin/python3",
|
||||
randomMetadata: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
baseHash: "abc123",
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -5,6 +5,8 @@ export const ExecApprovalsAllowlistEntrySchema = Type.Object(
|
||||
{
|
||||
id: Type.Optional(NonEmptyString),
|
||||
pattern: Type.String(),
|
||||
source: Type.Optional(Type.Literal("allow-always")),
|
||||
commandText: Type.Optional(Type.String()),
|
||||
argPattern: Type.Optional(Type.String()),
|
||||
lastUsedAt: Type.Optional(Type.Integer({ minimum: 0 })),
|
||||
lastUsedCommand: Type.Optional(Type.String()),
|
||||
|
||||
@@ -11,6 +11,9 @@ export type ExecApprovalsDefaults = {
|
||||
export type ExecApprovalsAllowlistEntry = {
|
||||
id?: string;
|
||||
pattern: string;
|
||||
source?: "allow-always";
|
||||
commandText?: string;
|
||||
argPattern?: string;
|
||||
lastUsedAt?: number;
|
||||
lastUsedCommand?: string;
|
||||
lastResolvedPath?: string;
|
||||
|
||||
Reference in New Issue
Block a user