test(plugins): harden kitchen sink external install

This commit is contained in:
Vincent Koc
2026-04-29 02:11:34 -07:00
parent 04c650c2c4
commit bc205836ca
3 changed files with 65 additions and 2 deletions

View File

@@ -17,12 +17,36 @@ const profiles = {
packageJson: {
name: packageName,
version: "0.1.3",
type: "module",
dependencies: {
"is-number": "7.0.0",
},
peerDependencies: {
openclaw: ">=2026.4.11",
},
peerDependenciesMeta: {
openclaw: {
optional: true,
},
},
openclaw: { extensions: ["./index.js"] },
},
indexJs: `module.exports = {
indexJs: `import isNumber from "is-number";
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
const dependencyUrl = import.meta.resolve("is-number");
const expectedDependencyBaseUrl = new URL("./node_modules/is-number/", import.meta.url).href;
if (!dependencyUrl.startsWith(expectedDependencyBaseUrl)) {
throw new Error(\`kitchen-sink dependency resolved outside plugin root: \${dependencyUrl}\`);
}
export default definePluginEntry({
id: "${pluginId}",
name: "OpenClaw Kitchen Sink",
register(api) {
if (!isNumber(42)) {
throw new Error("kitchen-sink dependency sentinel did not load");
}
api.registerProvider({
id: "kitchen-sink-provider",
label: "Kitchen Sink Provider",
@@ -48,7 +72,7 @@ const profiles = {
},
});
},
};
});
`,
manifest: {
id: pluginId,

View File

@@ -119,6 +119,38 @@ const expectIncludes = (listValue, expected, field) => {
}
};
function assertRealPathInside(parentPath, childPath, label) {
const parentRealPath = fs.realpathSync(parentPath);
const childRealPath = fs.realpathSync(childPath);
if (
childRealPath !== parentRealPath &&
!childRealPath.startsWith(`${parentRealPath}${path.sep}`)
) {
throw new Error(`${label} resolved outside ${parentPath}: ${childRealPath}`);
}
}
function assertClawHubExternalInstallContract(installPath) {
const openclawPeerPath = path.join(installPath, "node_modules", "openclaw");
if (!fs.existsSync(openclawPeerPath)) {
throw new Error(`missing kitchen-sink openclaw peer symlink: ${openclawPeerPath}`);
}
if (!fs.lstatSync(openclawPeerPath).isSymbolicLink()) {
throw new Error(`kitchen-sink openclaw peer is not a symlink: ${openclawPeerPath}`);
}
const hostRoot = fs.realpathSync(process.cwd());
const linkedHostRoot = fs.realpathSync(openclawPeerPath);
if (linkedHostRoot !== hostRoot) {
throw new Error(`expected kitchen-sink openclaw peer ${linkedHostRoot} to target ${hostRoot}`);
}
const dependencyPackagePath = path.join(installPath, "node_modules", "is-number", "package.json");
if (!fs.existsSync(dependencyPackagePath)) {
throw new Error(`missing kitchen-sink isolated dependency: ${dependencyPackagePath}`);
}
assertRealPathInside(installPath, dependencyPackagePath, "kitchen-sink isolated dependency");
}
function assertInstalled() {
const pluginId = process.env.KITCHEN_SINK_ID;
const spec = process.env.KITCHEN_SINK_SPEC;
@@ -270,6 +302,9 @@ function assertInstalled() {
if (!fs.existsSync(installPath)) {
throw new Error(`kitchen-sink install path missing: ${record.installPath}`);
}
if (source === "clawhub") {
assertClawHubExternalInstallContract(installPath);
}
fs.writeFileSync(`/tmp/kitchen-sink-${label}-install-path.txt`, installPath, "utf8");
}