mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 03:31:23 +00:00
fix(security): harden autoAllowSkills exec matching
This commit is contained in:
@@ -92,6 +92,10 @@ export function isSafeBinUsage(params: {
|
||||
return validateSafeBinArgv(argv, profile);
|
||||
}
|
||||
|
||||
function isPathScopedExecutableToken(token: string): boolean {
|
||||
return token.includes("/") || token.includes("\\");
|
||||
}
|
||||
|
||||
export type ExecAllowlistEvaluation = {
|
||||
allowlistSatisfied: boolean;
|
||||
allowlistMatches: ExecAllowlistEntry[];
|
||||
@@ -147,10 +151,19 @@ function evaluateSegments(
|
||||
platform: params.platform,
|
||||
trustedSafeBinDirs: params.trustedSafeBinDirs,
|
||||
});
|
||||
const skillAllow =
|
||||
allowSkills && segment.resolution?.executableName
|
||||
? params.skillBins?.has(segment.resolution.executableName)
|
||||
: false;
|
||||
const rawExecutable = segment.resolution?.rawExecutable?.trim() ?? "";
|
||||
const executableName = segment.resolution?.executableName;
|
||||
const usesExplicitPath = isPathScopedExecutableToken(rawExecutable);
|
||||
let skillAllow = false;
|
||||
if (
|
||||
allowSkills &&
|
||||
segment.resolution?.resolvedPath &&
|
||||
rawExecutable.length > 0 &&
|
||||
!usesExplicitPath &&
|
||||
executableName
|
||||
) {
|
||||
skillAllow = Boolean(params.skillBins?.has(executableName));
|
||||
}
|
||||
const by: ExecSegmentSatisfiedBy = match
|
||||
? "allowlist"
|
||||
: safe
|
||||
|
||||
@@ -627,6 +627,59 @@ describe("exec approvals allowlist evaluation", () => {
|
||||
});
|
||||
expect(result.allowlistSatisfied).toBe(true);
|
||||
});
|
||||
|
||||
it("does not satisfy auto-allow skills for explicit relative paths", () => {
|
||||
const analysis = {
|
||||
ok: true,
|
||||
segments: [
|
||||
{
|
||||
raw: "./skill-bin",
|
||||
argv: ["./skill-bin", "--help"],
|
||||
resolution: {
|
||||
rawExecutable: "./skill-bin",
|
||||
resolvedPath: "/tmp/skill-bin",
|
||||
executableName: "skill-bin",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
const result = evaluateExecAllowlist({
|
||||
analysis,
|
||||
allowlist: [],
|
||||
safeBins: new Set(),
|
||||
skillBins: new Set(["skill-bin"]),
|
||||
autoAllowSkills: true,
|
||||
cwd: "/tmp",
|
||||
});
|
||||
expect(result.allowlistSatisfied).toBe(false);
|
||||
expect(result.segmentSatisfiedBy).toEqual([null]);
|
||||
});
|
||||
|
||||
it("does not satisfy auto-allow skills when command resolution is missing", () => {
|
||||
const analysis = {
|
||||
ok: true,
|
||||
segments: [
|
||||
{
|
||||
raw: "skill-bin --help",
|
||||
argv: ["skill-bin", "--help"],
|
||||
resolution: {
|
||||
rawExecutable: "skill-bin",
|
||||
executableName: "skill-bin",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
const result = evaluateExecAllowlist({
|
||||
analysis,
|
||||
allowlist: [],
|
||||
safeBins: new Set(),
|
||||
skillBins: new Set(["skill-bin"]),
|
||||
autoAllowSkills: true,
|
||||
cwd: "/tmp",
|
||||
});
|
||||
expect(result.allowlistSatisfied).toBe(false);
|
||||
expect(result.segmentSatisfiedBy).toEqual([null]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("exec approvals policy helpers", () => {
|
||||
|
||||
Reference in New Issue
Block a user