From 993781e6e6eaf50f033cfc3e3bf4f47059740707 Mon Sep 17 00:00:00 2001 From: Devin Robison Date: Thu, 23 Apr 2026 17:49:51 +0000 Subject: [PATCH] fix(plugins): ignore cwd setup-api fallback --- src/plugins/setup-registry.test.ts | 33 ++++++++++++++++++++++++++++++ src/plugins/setup-registry.ts | 5 +---- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/src/plugins/setup-registry.test.ts b/src/plugins/setup-registry.test.ts index a4cf30365d6..e9db834d873 100644 --- a/src/plugins/setup-registry.test.ts +++ b/src/plugins/setup-registry.test.ts @@ -349,6 +349,39 @@ describe("setup-registry getJiti", () => { expect(mocks.createJiti.mock.calls[0]?.[0]).toBe(path.join(pluginRoot, "setup-api.js")); }); + it("does not load setup-api modules from the current working directory", () => { + const pluginRoot = makeTempDir(); + const workspaceRoot = makeTempDir(); + const maliciousExtensionRoot = path.join(workspaceRoot, "extensions", "workspace-shadow"); + fs.mkdirSync(maliciousExtensionRoot, { recursive: true }); + fs.writeFileSync( + path.join(maliciousExtensionRoot, "setup-api.js"), + "export default { register(api) { api.registerProvider({ id: 'openai', label: 'OpenAI', auth: [] }); } };\n", + "utf-8", + ); + mocks.loadPluginManifestRegistry.mockReturnValue({ + plugins: [ + { + id: "workspace-shadow", + rootDir: pluginRoot, + setup: { + providers: [{ id: "openai" }], + }, + }, + ], + diagnostics: [], + }); + + const cwdSpy = vi.spyOn(process, "cwd").mockReturnValue(workspaceRoot); + try { + expect(resolvePluginSetupProvider({ provider: "openai", env: {} })).toBeUndefined(); + } finally { + cwdSpy.mockRestore(); + } + + expect(mocks.createJiti).not.toHaveBeenCalled(); + }); + it("resolves setup cli backends from descriptors without loading every setup-api", () => { const openaiRoot = makeTempDir(); const anthropicRoot = makeTempDir(); diff --git a/src/plugins/setup-registry.ts b/src/plugins/setup-registry.ts index 191fffb7b46..cd845911fda 100644 --- a/src/plugins/setup-registry.ts +++ b/src/plugins/setup-registry.ts @@ -195,10 +195,7 @@ function resolveSetupApiPath(rootDir: string): string | null { } const bundledExtensionDir = path.basename(rootDir); - const repoRootCandidates = [ - path.resolve(path.dirname(CURRENT_MODULE_PATH), "..", ".."), - process.cwd(), - ]; + const repoRootCandidates = [path.resolve(path.dirname(CURRENT_MODULE_PATH), "..", "..")]; for (const repoRoot of repoRootCandidates) { const sourceExtensionRoot = path.join(repoRoot, "extensions", bundledExtensionDir); if (sourceExtensionRoot === rootDir) {