fix: align skill install security gate

This commit is contained in:
Peter Steinberger
2026-03-31 15:51:58 +01:00
parent 192484ed0a
commit bf96c67fd1
4 changed files with 142 additions and 201 deletions

View File

@@ -445,3 +445,66 @@ export async function scanFileInstallSourceRuntime(
});
return hookResult?.blocked ? hookResult : builtinBlocked;
}
export async function scanSkillInstallSourceRuntime(params: {
dangerouslyForceUnsafeInstall?: boolean;
installId: string;
installSpec?: {
id?: string;
kind: "brew" | "node" | "go" | "uv" | "download";
label?: string;
bins?: string[];
os?: string[];
formula?: string;
package?: string;
module?: string;
url?: string;
archive?: string;
extract?: boolean;
stripComponents?: number;
targetDir?: string;
};
logger: InstallScanLogger;
origin: string;
skillName: string;
sourceDir: string;
}): Promise<InstallSecurityScanResult | undefined> {
const builtinScan = await scanDirectoryTarget({
logger: params.logger,
path: params.sourceDir,
suspiciousMessage:
'Skill "{target}" has {count} suspicious code pattern(s). Run "openclaw security audit --deep" for details.',
targetName: params.skillName,
warningMessage: `WARNING: Skill "${params.skillName}" contains dangerous code patterns`,
});
const builtinBlocked = buildBlockedScanResult({
builtinScan,
dangerouslyForceUnsafeInstall: params.dangerouslyForceUnsafeInstall,
targetLabel: `Skill "${params.skillName}" installation`,
});
if (params.dangerouslyForceUnsafeInstall && builtinScan.critical > 0) {
logDangerousForceUnsafeInstall({
findings: builtinScan.findings,
logger: params.logger,
targetLabel: `Skill "${params.skillName}" installation`,
});
}
const hookResult = await runBeforeInstallHook({
logger: params.logger,
installLabel: `Skill "${params.skillName}" installation`,
origin: params.origin,
sourcePath: params.sourceDir,
sourcePathKind: "directory",
targetName: params.skillName,
targetType: "skill",
requestKind: "skill-install",
requestMode: "install",
builtinScan,
skill: {
installId: params.installId,
...(params.installSpec ? { installSpec: params.installSpec } : {}),
},
});
return hookResult?.blocked ? hookResult : builtinBlocked;
}

View File

@@ -19,6 +19,22 @@ export type PluginInstallRequestKind =
| "plugin-file"
| "plugin-npm";
export type SkillInstallSpecMetadata = {
id?: string;
kind: "brew" | "node" | "go" | "uv" | "download";
label?: string;
bins?: string[];
os?: string[];
formula?: string;
package?: string;
module?: string;
url?: string;
archive?: string;
extract?: boolean;
stripComponents?: number;
targetDir?: string;
};
async function loadInstallSecurityScanRuntime() {
return await import("./install-security-scan.runtime.js");
}
@@ -68,3 +84,16 @@ export async function scanFileInstallSource(
const { scanFileInstallSourceRuntime } = await loadInstallSecurityScanRuntime();
return await scanFileInstallSourceRuntime(params);
}
export async function scanSkillInstallSource(params: {
dangerouslyForceUnsafeInstall?: boolean;
installId: string;
installSpec?: SkillInstallSpecMetadata;
logger: InstallScanLogger;
origin: string;
skillName: string;
sourceDir: string;
}): Promise<InstallSecurityScanResult | undefined> {
const { scanSkillInstallSourceRuntime } = await loadInstallSecurityScanRuntime();
return await scanSkillInstallSourceRuntime(params);
}