From fc60ced03c6cf3d6be772d07b7e0b785fb965d47 Mon Sep 17 00:00:00 2001 From: scoootscooob Date: Tue, 24 Mar 2026 10:38:52 -0700 Subject: [PATCH] Plugins: trust only startup cli sdk roots --- src/plugins/sdk-alias.test.ts | 13 ++++++++---- src/plugins/sdk-alias.ts | 40 +++++++++++++++++++++++++++++------ 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/src/plugins/sdk-alias.test.ts b/src/plugins/sdk-alias.test.ts index 1459f254e47..77eb07f9cec 100644 --- a/src/plugins/sdk-alias.test.ts +++ b/src/plugins/sdk-alias.test.ts @@ -255,7 +255,12 @@ describe("plugin sdk alias helpers", () => { }, { name: "resolves plugin-sdk alias from package root when loader runs from transpiler cache path", - buildFixture: () => createPluginSdkAliasFixture(), + buildFixture: () => + createPluginSdkAliasFixture({ + packageExports: { + "./plugin-sdk/index": { default: "./dist/plugin-sdk/index.js" }, + }, + }), modulePath: () => "/tmp/tsx-cache/openclaw-loader.js", argv1: (root: string) => path.join(root, "openclaw.mjs"), srcFile: "index.ts", @@ -486,9 +491,9 @@ describe("plugin sdk alias helpers", () => { mkdirSafe(externalPluginRoot); fs.writeFileSync(externalPluginEntry, 'export const plugin = "demo";\n', "utf-8"); - const aliases = withArgv1(path.join(fixture.root, "openclaw.mjs"), () => - withCwd(externalPluginRoot, () => - withEnv({ NODE_ENV: undefined }, () => buildPluginLoaderAliasMap(externalPluginEntry)), + const aliases = withCwd(externalPluginRoot, () => + withEnv({ NODE_ENV: undefined }, () => + buildPluginLoaderAliasMap(externalPluginEntry, path.join(fixture.root, "openclaw.mjs")), ), ); diff --git a/src/plugins/sdk-alias.ts b/src/plugins/sdk-alias.ts index a9dff7f1a98..ee6a3b0641a 100644 --- a/src/plugins/sdk-alias.ts +++ b/src/plugins/sdk-alias.ts @@ -17,6 +17,8 @@ type PluginSdkPackageJson = { bin?: string | Record; }; +const STARTUP_ARGV1 = process.argv[1]; + function resolveLoaderModulePath(params: LoaderModuleResolveParams = {}): string { return params.modulePath ?? fileURLToPath(params.moduleUrl ?? import.meta.url); } @@ -73,6 +75,27 @@ function readPluginSdkSubpathsFromPackageRoot(packageRoot: string): string[] | n return subpaths.length > 0 ? subpaths : null; } +function resolveTrustedOpenClawRootFromArgvHint(params: { + argv1?: string; + cwd: string; +}): string | null { + if (!params.argv1) { + return null; + } + const packageRoot = resolveOpenClawPackageRootSync({ + cwd: params.cwd, + argv1: params.argv1, + }); + if (!packageRoot) { + return null; + } + const packageJson = readPluginSdkPackageJson(packageRoot); + if (!packageJson) { + return null; + } + return hasTrustedOpenClawRootIndicator({ packageRoot, packageJson }) ? packageRoot : null; +} + function findNearestPluginSdkPackageRoot(startDir: string, maxDepth = 12): string | null { let cursor = path.resolve(startDir); for (let i = 0; i < maxDepth; i += 1) { @@ -112,13 +135,13 @@ function resolveLoaderPluginSdkPackageRoot( const cwd = params.cwd ?? path.dirname(params.modulePath); const fromCwd = resolveOpenClawPackageRootSync({ cwd }); const fromExplicitHints = - params.argv1 || params.moduleUrl + resolveTrustedOpenClawRootFromArgvHint({ cwd, argv1: params.argv1 }) ?? + (params.moduleUrl ? resolveOpenClawPackageRootSync({ cwd, - ...(params.argv1 ? { argv1: params.argv1 } : {}), - ...(params.moduleUrl ? { moduleUrl: params.moduleUrl } : {}), + moduleUrl: params.moduleUrl, }) - : null; + : null); return ( fromCwd ?? fromExplicitHints ?? @@ -287,18 +310,21 @@ export function resolveExtensionApiAlias(params: LoaderModuleResolveParams = {}) return null; } -export function buildPluginLoaderAliasMap(modulePath: string): Record { +export function buildPluginLoaderAliasMap( + modulePath: string, + argv1: string | undefined = STARTUP_ARGV1, +): Record { const pluginSdkAlias = resolvePluginSdkAliasFile({ srcFile: "root-alias.cjs", distFile: "root-alias.cjs", modulePath, - argv1: process.argv[1], + argv1, }); const extensionApiAlias = resolveExtensionApiAlias({ modulePath }); return { ...(extensionApiAlias ? { "openclaw/extension-api": extensionApiAlias } : {}), ...(pluginSdkAlias ? { "openclaw/plugin-sdk": pluginSdkAlias } : {}), - ...resolvePluginSdkScopedAliasMap({ modulePath, argv1: process.argv[1] }), + ...resolvePluginSdkScopedAliasMap({ modulePath, argv1 }), }; }