@@ -17,7 +17,7 @@ import {
1717 type PackageManifest ,
1818 type PluginPackageChannel ,
1919} from "./manifest.js" ;
20- import { isPathInsideWithRealpath , safeRealpathSync } from "./path-safety.js" ;
20+ import { isPathInside , safeRealpathSync } from "./path-safety.js" ;
2121import { tracePluginLifecyclePhase } from "./plugin-lifecycle-trace.js" ;
2222import {
2323 normalizePluginDependencySpecs ,
@@ -33,18 +33,22 @@ function isRelativePathInsideOrEqual(relativePath: string): boolean {
3333 ) ;
3434}
3535
36- function resolvePackageJsonPath ( record : InstalledPluginIndexRecord ) : string | undefined {
36+ function resolvePackageJsonPath (
37+ record : InstalledPluginIndexRecord ,
38+ realpathCache : Map < string , string > ,
39+ ) : string | undefined {
3740 if ( ! record . packageJson ?. path ) {
3841 return undefined ;
3942 }
4043 const rootDir = resolveInstalledPluginRootDir ( record ) ;
41- const realRootDir = safeRealpathSync ( rootDir ) ?? path . resolve ( rootDir ) ;
44+ const realRootDir = safeRealpathSync ( rootDir , realpathCache ) ?? path . resolve ( rootDir ) ;
4245 const packageJsonPath = path . resolve ( realRootDir , record . packageJson . path ) ;
4346 const relative = path . relative ( realRootDir , packageJsonPath ) ;
4447 if ( ! isRelativePathInsideOrEqual ( relative ) ) {
4548 return undefined ;
4649 }
47- if ( ! isPathInsideWithRealpath ( realRootDir , packageJsonPath ) ) {
50+ const packageJsonRealPath = safeRealpathSync ( packageJsonPath , realpathCache ) ;
51+ if ( ! packageJsonRealPath || ! isPathInside ( realRootDir , packageJsonRealPath ) ) {
4852 return undefined ;
4953 }
5054 return packageJsonPath ;
@@ -63,6 +67,7 @@ function safeFileSignature(filePath: string | undefined): string | undefined {
6367}
6468
6569function buildInstalledManifestRegistryIndexKey ( index : InstalledPluginIndex ) {
70+ const realpathCache = new Map < string , string > ( ) ;
6671 return {
6772 version : index . version ,
6873 hostContractVersion : index . hostContractVersion ,
@@ -72,7 +77,7 @@ function buildInstalledManifestRegistryIndexKey(index: InstalledPluginIndex) {
7277 installRecords : index . installRecords ,
7378 diagnostics : index . diagnostics ,
7479 plugins : index . plugins . map ( ( record ) => {
75- const packageJsonPath = resolvePackageJsonPath ( record ) ;
80+ const packageJsonPath = resolvePackageJsonPath ( record , realpathCache ) ;
7681 return {
7782 pluginId : record . pluginId ,
7883 packageName : record . packageName ,
@@ -359,7 +364,10 @@ function normalizePersistedPackageChannel(value: unknown): PluginPackageChannel
359364 return channel ;
360365}
361366
362- function resolveInstalledPackageMetadata ( record : InstalledPluginIndexRecord ) : {
367+ function resolveInstalledPackageMetadata (
368+ record : InstalledPluginIndexRecord ,
369+ realpathCache : Map < string , string > ,
370+ ) : {
363371 packageManifest ?: OpenClawPackageManifest ;
364372 packageDependencies ?: PluginDependencySpecMap ;
365373 packageOptionalDependencies ?: PluginDependencySpecMap ;
@@ -370,7 +378,9 @@ function resolveInstalledPackageMetadata(record: InstalledPluginIndexRecord): {
370378 channel : recordPackageChannel ,
371379 }
372380 : undefined ;
373- const packageJsonPath = record . packageJson ?. path ? resolvePackageJsonPath ( record ) : undefined ;
381+ const packageJsonPath = record . packageJson ?. path
382+ ? resolvePackageJsonPath ( record , realpathCache )
383+ : undefined ;
374384 if ( ! packageJsonPath ) {
375385 return fallbackPackageManifest ? { packageManifest : fallbackPackageManifest } : { } ;
376386 }
@@ -409,9 +419,12 @@ function resolveInstalledPackageMetadata(record: InstalledPluginIndexRecord): {
409419 return fallbackPackageManifest ? { packageManifest : fallbackPackageManifest } : { } ;
410420}
411421
412- function toPluginCandidate ( record : InstalledPluginIndexRecord ) : PluginCandidate {
422+ function toPluginCandidate (
423+ record : InstalledPluginIndexRecord ,
424+ realpathCache : Map < string , string > ,
425+ ) : PluginCandidate {
413426 const rootDir = resolveInstalledPluginRootDir ( record ) ;
414- const packageMetadata = resolveInstalledPackageMetadata ( record ) ;
427+ const packageMetadata = resolveInstalledPackageMetadata ( record , realpathCache ) ;
415428 return {
416429 idHint : record . pluginId ,
417430 source : record . source ?? resolveFallbackPluginSource ( record ) ,
@@ -452,6 +465,7 @@ export function loadPluginManifestRegistryForInstalledIndex(params: {
452465 }
453466 const env = params . env ?? process . env ;
454467 const pluginIdSet = params . pluginIds ?. length ? new Set ( params . pluginIds ) : null ;
468+ const realpathCache = new Map < string , string > ( ) ;
455469 const diagnostics = pluginIdSet
456470 ? params . index . diagnostics . filter ( ( diagnostic ) => {
457471 const pluginId = diagnostic . pluginId ;
@@ -461,7 +475,7 @@ export function loadPluginManifestRegistryForInstalledIndex(params: {
461475 const candidates = params . index . plugins
462476 . filter ( ( plugin ) => params . includeDisabled || plugin . enabled )
463477 . filter ( ( plugin ) => ! pluginIdSet || pluginIdSet . has ( plugin . pluginId ) )
464- . map ( toPluginCandidate ) ;
478+ . map ( ( plugin ) => toPluginCandidate ( plugin , realpathCache ) ) ;
465479 return loadPluginManifestRegistry ( {
466480 config : params . config ,
467481 workspaceDir : params . workspaceDir ,
0 commit comments