From 0d1d405a7269558610bcadf1081ee3f536afc4c4 Mon Sep 17 00:00:00 2001 From: Robin Mordasiewicz Date: Sat, 14 Mar 2026 05:35:12 +0000 Subject: [PATCH] fix(discovery): add null-safe validation for v3 array entries Filter out null, undefined, or malformed entries in installed_plugins.json before accessing properties. Prevents fatal crash on corrupted data. Addresses cubic-dev-ai review feedback. --- dist/index.js | 5 ++++- .../claude-code-plugin-loader/discovery.ts | 20 +++++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/dist/index.js b/dist/index.js index 6d9624b9d..fdc530924 100644 --- a/dist/index.js +++ b/dist/index.js @@ -19452,9 +19452,12 @@ function v3EntryToInstallation(entry) { gitCommitSha: entry.gitCommitSha }; } +function isValidV3Entry(entry) { + return entry != null && typeof entry === "object" && typeof entry.name === "string" && typeof entry.marketplace === "string" && typeof entry.installPath === "string"; +} function extractPluginEntries(db) { if (Array.isArray(db)) { - return db.map((entry) => [ + return db.filter(isValidV3Entry).map((entry) => [ `${entry.name}@${entry.marketplace}`, v3EntryToInstallation(entry) ]); diff --git a/src/features/claude-code-plugin-loader/discovery.ts b/src/features/claude-code-plugin-loader/discovery.ts index 767c974f9..f2ec3d0be 100644 --- a/src/features/claude-code-plugin-loader/discovery.ts +++ b/src/features/claude-code-plugin-loader/discovery.ts @@ -108,14 +108,26 @@ function v3EntryToInstallation(entry: InstalledPluginEntryV3): PluginInstallatio } } +function isValidV3Entry(entry: unknown): entry is InstalledPluginEntryV3 { + return ( + entry != null && + typeof entry === "object" && + typeof (entry as Record).name === "string" && + typeof (entry as Record).marketplace === "string" && + typeof (entry as Record).installPath === "string" + ) +} + function extractPluginEntries( db: InstalledPluginsDatabase, ): Array<[string, PluginInstallation | undefined]> { if (Array.isArray(db)) { - return db.map((entry) => [ - `${entry.name}@${entry.marketplace}`, - v3EntryToInstallation(entry), - ]) + return db + .filter(isValidV3Entry) + .map((entry) => [ + `${entry.name}@${entry.marketplace}`, + v3EntryToInstallation(entry), + ]) } if (db.version === 1) { return Object.entries(db.plugins).map(([key, installation]) => [key, installation])