@@ -247,6 +247,28 @@ const getChildNode = (
247247 ) ;
248248
249249 if ( ! childNodeKey ) {
250+ // https://snyksec.atlassian.net/wiki/spaces/SCA/pages/3785687123/NPM+Bundled+Dependencies+Analysis
251+ // Check if this dependency is bundled in the parent package
252+ // Bundled dependencies may not have separate lockfile entries when
253+ // the package is installed from registry (they're pre-packaged in the tarball)
254+ const parentNode = ancestry [ ancestry . length - 1 ] ;
255+ if ( parentNode && parentNode . key ) {
256+ const parentPkg = pkgs [ parentNode . key ] ;
257+ if ( parentPkg && isBundledDependency ( name , parentPkg ) ) {
258+ // This is a bundled dependency without a lockfile entry
259+ // Return a placeholder node - we don't have sub-dependency information
260+ return {
261+ id : `${ name } @${ depInfo . version } ` ,
262+ name : name ,
263+ version : '' , // empty version since we cannot resolve the semver for bundled deps
264+ dependencies : { } ,
265+ isDev : depInfo . isDev ,
266+ inBundle : true ,
267+ key : '' ,
268+ } ;
269+ }
270+ }
271+
250272 if ( strictOutOfSync ) {
251273 throw new OutOfSyncError ( `${ name } @${ depInfo . version } ` , LockfileType . npm ) ;
252274 } else {
@@ -323,6 +345,20 @@ const getChildNode = (
323345 } ;
324346} ;
325347
348+ // Checks if a dependency is bundled in the parent package.
349+ // Bundled dependencies are included in the parent's published tarball
350+ // and may not have separate entries in the lockfile when installed from registry.
351+ function isBundledDependency ( depName : string , parentPkg : NpmLockPkg ) : boolean {
352+ // Check both spellings (bundleDependencies is canonical, bundledDependencies is alternative)
353+ const bundled = parentPkg . bundleDependencies || parentPkg . bundledDependencies ;
354+
355+ if ( ! bundled || ! Array . isArray ( bundled ) ) {
356+ return false ;
357+ }
358+
359+ return bundled . includes ( depName ) ;
360+ }
361+
326362export const getChildNodeKey = (
327363 name : string ,
328364 version : string ,
@@ -433,7 +469,7 @@ export const getChildNodeKey = (
433469 ancestryNames . shift ( ) ;
434470 }
435471
436- // Here we go through th eancestry backwards to find the nearest
472+ // Here we go through the ancestry backwards to find the nearest
437473 // ancestor package
438474 const reversedAncestry = ancestry . reverse ( ) ;
439475 for (
0 commit comments