



























@@ -134,20 +134,26 @@ function runAssertInstalled({
134134135135function runAssertClawhubInstalled({
136136 contextEngineIds = [],
137+ installPathRelative,
137138}: {
138139contextEngineIds?: string[];
140+installPathRelative?: string;
139141} = {}) {
140142const label = `clawhub-context-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`;
141143const pluginId = "openclaw-kitchen-sink-fixture";
142144const home = mkdtempSync(path.join(tmpdir(), "openclaw-kitchen-sink-home-"));
143-const installPath = mkdtempSync(path.join(tmpdir(), "openclaw-kitchen-sink-install-"));
145+const installPath = installPathRelative
146+ ? `${home}${path.sep}${installPathRelative}`
147+ : path.join(home, ".openclaw", "extensions", pluginId);
144148const scratchRoot = tmpdir();
145149const pluginsJsonPath = path.join(scratchRoot, `kitchen-sink-${label}-plugins.json`);
146150const inspectJsonPath = path.join(scratchRoot, `kitchen-sink-${label}-inspect.json`);
147151const inspectAllJsonPath = path.join(scratchRoot, `kitchen-sink-${label}-inspect-all.json`);
148152const installPathMarker = path.join(scratchRoot, `kitchen-sink-${label}-install-path.txt`);
149153const installsPath = path.join(home, ".openclaw", "plugins", "installs.json");
150154try {
155+mkdirSync(path.join(home, ".openclaw", "extensions"), { recursive: true });
156+mkdirSync(installPath, { recursive: true });
151157const inspectPayload = fullSurfaceInspectPayload(pluginId);
152158inspectPayload.plugin.contextEngineIds = contextEngineIds;
153159writeJson(pluginsJsonPath, {
@@ -191,7 +197,6 @@ function runAssertClawhubInstalled({
191197});
192198} finally {
193199rmSync(home, { force: true, recursive: true });
194-rmSync(installPath, { force: true, recursive: true });
195200rmSync(pluginsJsonPath, { force: true });
196201rmSync(inspectJsonPath, { force: true });
197202rmSync(inspectAllJsonPath, { force: true });
@@ -327,6 +332,16 @@ describe("kitchen-sink plugin assertions", () => {
327332expect(result.status).toBe(0);
328333});
329334335+it("rejects ClawHub kitchen-sink install paths that resolve outside managed extensions", () => {
336+const result = runAssertClawhubInstalled({
337+contextEngineIds: ["openclaw-kitchen-sink-fixture"],
338+installPathRelative: [".openclaw", "extensions", "..", "escaped-kitchen-sink"].join(path.sep),
339+});
340+341+expect(result.status).not.toBe(0);
342+expect(result.stderr).toContain("kitchen-sink ClawHub install path resolved outside");
343+});
344+330345it("keeps exhaustive diagnostic matching available for synchronized fixtures", () => {
331346const result = runAssertInstalled({
332347diagnostics: diagnosticErrors(REQUIRED_FULL_DIAGNOSTIC_CANARIES),
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。