mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-07 23:11:25 +00:00
test(exec): add regressions for safe-bin metadata and chain semantics
This commit is contained in:
@@ -680,6 +680,71 @@ describe("exec approvals allowlist evaluation", () => {
|
|||||||
expect(result.allowlistSatisfied).toBe(false);
|
expect(result.allowlistSatisfied).toBe(false);
|
||||||
expect(result.segmentSatisfiedBy).toEqual([null]);
|
expect(result.segmentSatisfiedBy).toEqual([null]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("returns empty segment details for chain misses", () => {
|
||||||
|
const segment = {
|
||||||
|
raw: "tool",
|
||||||
|
argv: ["tool"],
|
||||||
|
resolution: {
|
||||||
|
rawExecutable: "tool",
|
||||||
|
resolvedPath: "/usr/bin/tool",
|
||||||
|
executableName: "tool",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const analysis = {
|
||||||
|
ok: true,
|
||||||
|
segments: [segment],
|
||||||
|
chains: [[segment]],
|
||||||
|
};
|
||||||
|
const result = evaluateExecAllowlist({
|
||||||
|
analysis,
|
||||||
|
allowlist: [{ pattern: "/usr/bin/other" }],
|
||||||
|
safeBins: new Set(),
|
||||||
|
cwd: "/tmp",
|
||||||
|
});
|
||||||
|
expect(result.allowlistSatisfied).toBe(false);
|
||||||
|
expect(result.allowlistMatches).toEqual([]);
|
||||||
|
expect(result.segmentSatisfiedBy).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("aggregates segment satisfaction across chains", () => {
|
||||||
|
const allowlistSegment = {
|
||||||
|
raw: "tool",
|
||||||
|
argv: ["tool"],
|
||||||
|
resolution: {
|
||||||
|
rawExecutable: "tool",
|
||||||
|
resolvedPath: "/usr/bin/tool",
|
||||||
|
executableName: "tool",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const safeBinSegment = {
|
||||||
|
raw: "jq .foo",
|
||||||
|
argv: ["jq", ".foo"],
|
||||||
|
resolution: {
|
||||||
|
rawExecutable: "jq",
|
||||||
|
resolvedPath: "/usr/bin/jq",
|
||||||
|
executableName: "jq",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const analysis = {
|
||||||
|
ok: true,
|
||||||
|
segments: [allowlistSegment, safeBinSegment],
|
||||||
|
chains: [[allowlistSegment], [safeBinSegment]],
|
||||||
|
};
|
||||||
|
const result = evaluateExecAllowlist({
|
||||||
|
analysis,
|
||||||
|
allowlist: [{ pattern: "/usr/bin/tool" }],
|
||||||
|
safeBins: normalizeSafeBins(["jq"]),
|
||||||
|
cwd: "/tmp",
|
||||||
|
});
|
||||||
|
if (process.platform === "win32") {
|
||||||
|
expect(result.allowlistSatisfied).toBe(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
expect(result.allowlistSatisfied).toBe(true);
|
||||||
|
expect(result.allowlistMatches.map((entry) => entry.pattern)).toEqual(["/usr/bin/tool"]);
|
||||||
|
expect(result.segmentSatisfiedBy).toEqual(["allowlist", "safeBins"]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("exec approvals policy helpers", () => {
|
describe("exec approvals policy helpers", () => {
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import { describe, expect, it } from "vitest";
|
|||||||
import {
|
import {
|
||||||
SAFE_BIN_PROFILE_FIXTURES,
|
SAFE_BIN_PROFILE_FIXTURES,
|
||||||
SAFE_BIN_PROFILES,
|
SAFE_BIN_PROFILES,
|
||||||
|
buildLongFlagPrefixMap,
|
||||||
|
collectKnownLongFlags,
|
||||||
renderSafeBinDeniedFlagsDocBullets,
|
renderSafeBinDeniedFlagsDocBullets,
|
||||||
validateSafeBinArgv,
|
validateSafeBinArgv,
|
||||||
} from "./exec-safe-bin-policy.js";
|
} from "./exec-safe-bin-policy.js";
|
||||||
@@ -76,6 +78,38 @@ describe("exec safe bin policy wc", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("exec safe bin policy long-option metadata", () => {
|
||||||
|
it("precomputes long-option prefix mappings for compiled profiles", () => {
|
||||||
|
const sortProfile = SAFE_BIN_PROFILES.sort;
|
||||||
|
expect(sortProfile.knownLongFlagsSet?.has("--compress-program")).toBe(true);
|
||||||
|
expect(sortProfile.longFlagPrefixMap?.get("--compress-prog")).toBe("--compress-program");
|
||||||
|
expect(sortProfile.longFlagPrefixMap?.get("--f")).toBe(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("preserves behavior when profile metadata is missing and rebuilt at runtime", () => {
|
||||||
|
const sortProfile = SAFE_BIN_PROFILES.sort;
|
||||||
|
const withoutMetadata = {
|
||||||
|
...sortProfile,
|
||||||
|
knownLongFlags: undefined,
|
||||||
|
knownLongFlagsSet: undefined,
|
||||||
|
longFlagPrefixMap: undefined,
|
||||||
|
};
|
||||||
|
expect(validateSafeBinArgv(["--compress-prog=sh"], withoutMetadata)).toBe(false);
|
||||||
|
expect(validateSafeBinArgv(["--totally-unknown=1"], withoutMetadata)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("builds prefix maps from collected long flags", () => {
|
||||||
|
const sortProfile = SAFE_BIN_PROFILES.sort;
|
||||||
|
const flags = collectKnownLongFlags(
|
||||||
|
sortProfile.allowedValueFlags ?? new Set(),
|
||||||
|
sortProfile.deniedFlags ?? new Set(),
|
||||||
|
);
|
||||||
|
const prefixMap = buildLongFlagPrefixMap(flags);
|
||||||
|
expect(prefixMap.get("--compress-pr")).toBe("--compress-program");
|
||||||
|
expect(prefixMap.get("--f")).toBe(null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("exec safe bin policy denied-flag matrix", () => {
|
describe("exec safe bin policy denied-flag matrix", () => {
|
||||||
for (const [binName, fixture] of Object.entries(SAFE_BIN_PROFILE_FIXTURES)) {
|
for (const [binName, fixture] of Object.entries(SAFE_BIN_PROFILE_FIXTURES)) {
|
||||||
const profile = SAFE_BIN_PROFILES[binName];
|
const profile = SAFE_BIN_PROFILES[binName];
|
||||||
|
|||||||
Reference in New Issue
Block a user