




















@@ -191,6 +191,20 @@ function primeHookPackNpmFallback() {
191191return { cfg, installedCfg };
192192}
193193194+function primeBlockedNpmPluginInstall(params: {
195+spec: string;
196+pluginId: string;
197+code?: "security_scan_blocked" | "security_scan_failed";
198+}) {
199+loadConfig.mockReturnValue({} as OpenClawConfig);
200+mockClawHubPackageNotFound(params.spec);
201+installPluginFromNpmSpec.mockResolvedValue({
202+ok: false,
203+error: `Plugin "${params.pluginId}" installation blocked: dangerous code patterns detected: finding details`,
204+code: params.code ?? "security_scan_blocked",
205+});
206+}
207+194208function primeHookPackPathFallback(params: {
195209tmpRoot: string;
196210pluginInstallError: string;
@@ -606,6 +620,30 @@ describe("plugins cli install", () => {
606620);
607621});
608622623+it("does not fall back to hook pack for linked path when a no-flag security scan blocks", async () => {
624+const localPluginDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-link-plugin-"));
625+const pluginInstallError = "plugin blocked by security scan";
626+627+loadConfig.mockReturnValue({} as OpenClawConfig);
628+installPluginFromPath.mockResolvedValue({
629+ok: false,
630+error: pluginInstallError,
631+code: "security_scan_blocked",
632+});
633+634+try {
635+await expect(
636+runPluginsCommand(["plugins", "install", localPluginDir, "--link"]),
637+).rejects.toThrow("__exit__:1");
638+} finally {
639+fs.rmSync(localPluginDir, { recursive: true, force: true });
640+}
641+642+expect(installHooksFromPath).not.toHaveBeenCalled();
643+expect(runtimeErrors.at(-1)).toContain(pluginInstallError);
644+expect(runtimeErrors.at(-1)).not.toContain("Also not a valid hook pack");
645+});
646+609647it("passes dangerous force unsafe install to local hook-pack fallback installs", async () => {
610648const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-hook-install-"));
611649primeHookPackPathFallback({
@@ -740,6 +778,30 @@ describe("plugins cli install", () => {
740778).toBe(true);
741779});
742780781+it("does not fall back to hook pack for local path when a no-flag security scan fails", async () => {
782+const localPluginDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-local-plugin-"));
783+const pluginInstallError = "plugin security scan failed";
784+785+loadConfig.mockReturnValue({} as OpenClawConfig);
786+installPluginFromPath.mockResolvedValue({
787+ok: false,
788+error: pluginInstallError,
789+code: "security_scan_failed",
790+});
791+792+try {
793+await expect(runPluginsCommand(["plugins", "install", localPluginDir])).rejects.toThrow(
794+"__exit__:1",
795+);
796+} finally {
797+fs.rmSync(localPluginDir, { recursive: true, force: true });
798+}
799+800+expect(installHooksFromPath).not.toHaveBeenCalled();
801+expect(runtimeErrors.at(-1)).toContain(pluginInstallError);
802+expect(runtimeErrors.at(-1)).not.toContain("Also not a valid hook pack");
803+});
804+743805it("does not fall back to hook pack for local path when dangerous force unsafe install is set", async () => {
744806const localPluginDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-local-plugin-"));
745807const cfg = {} as OpenClawConfig;
@@ -822,6 +884,21 @@ describe("plugins cli install", () => {
822884expect(runtimeErrors.at(-1)).toContain(pluginInstallError);
823885});
824886887+it("does not fall back to hook pack for npm installs when a no-flag security scan blocks", async () => {
888+primeBlockedNpmPluginInstall({
889+spec: "@acme/unsafe-plugin",
890+pluginId: "unsafe-plugin",
891+});
892+893+await expect(runPluginsCommand(["plugins", "install", "@acme/unsafe-plugin"])).rejects.toThrow(
894+"__exit__:1",
895+);
896+897+expect(installHooksFromNpmSpec).not.toHaveBeenCalled();
898+expect(runtimeErrors.at(-1)).toContain('Plugin "unsafe-plugin" installation blocked');
899+expect(runtimeErrors.at(-1)).not.toContain("Also not a valid hook pack");
900+});
901+825902it("does not fall back to hook pack for npm installs when security scan fails under dangerous force unsafe install", async () => {
826903const cfg = {} as OpenClawConfig;
827904const pluginInstallError = "plugin security scan failed";
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。