From 99d8b79d09980335a15097b4c6853ccdda64e0a0 Mon Sep 17 00:00:00 2001 From: natashz Date: Tue, 7 Jan 2025 22:08:14 +0200 Subject: [PATCH 1/5] feat: add additional metadata for manifest files feat: extract repoUrl from nodejs manifest --- lib/analyzer/applications/runtime-common.ts | 91 ++++++++-- lib/analyzer/applications/types.ts | 6 +- test/lib/analyzer/runtime-commons.spec.ts | 170 ++++++++++++++++++ test/system/application-scans/node.spec.ts | 74 +------- .../application-scans/python/pip.spec.ts | 32 ---- 5 files changed, 253 insertions(+), 120 deletions(-) create mode 100644 test/lib/analyzer/runtime-commons.spec.ts diff --git a/lib/analyzer/applications/runtime-common.ts b/lib/analyzer/applications/runtime-common.ts index f7427869..76834dc7 100644 --- a/lib/analyzer/applications/runtime-common.ts +++ b/lib/analyzer/applications/runtime-common.ts @@ -1,4 +1,5 @@ import * as path from "path"; +import { parsePkgJson } from "snyk-nodejs-lockfile-parser"; import { ApplicationFilesFact } from "../../facts"; import { AppDepsScanResultWithoutTarget, @@ -6,18 +7,76 @@ import { FilePathToContent, } from "./types"; -export function getAppFilesRootDir( - filePaths: string[], -): [string, ApplicationFileInfo[]] { +interface AppFileMetadataExtractor { + manifestFiles: string[]; + metadataExtractor: (fileContent: string) => Record; +} + +export const filesMetadataExtractorPerLanguage: Record< + string, + AppFileMetadataExtractor +> = { + node: { + manifestFiles: ["package.json", "package-lock.json", "yarn.lock"], + metadataExtractor: (fileContent: string) => { + const pkgJson = parsePkgJson(fileContent); + const repoUrl = (pkgJson as any).repository?.url; + return { + moduleName: pkgJson.name, + repoUrl, + }; + }, + }, +}; + +export function getAppFileInfos( + filePathToContent: FilePathToContent, + rootDir: string, + manifestMetadataExtractor?: AppFileMetadataExtractor, +): ApplicationFileInfo[] { const appFiles: ApplicationFileInfo[] = []; - const splitPaths: string[][] = []; + const filePaths = Object.keys(filePathToContent); if (!filePaths.length) { - return [path.sep, appFiles]; + return appFiles; } for (const filePath of filePaths) { - appFiles.push({ path: filePath }); + const appFile: ApplicationFileInfo = { path: filePath }; + if (manifestMetadataExtractor) { + const { manifestFiles, metadataExtractor } = manifestMetadataExtractor; + if ( + manifestFiles.length && + manifestFiles.some((mf) => filePath.endsWith("/" + mf)) + ) { + appFile.type = "Manifest"; + const manifestContent = filePathToContent[filePath]; + + appFile.metadata = metadataExtractor(manifestContent); + } + } + + appFiles.push(appFile); + } + + // Remove the common path prefix from each appFile + appFiles.forEach((file) => { + const prefix = rootDir === path.sep ? rootDir : `${rootDir}${path.sep}`; + if (file.path.startsWith(prefix)) { + file.path = file.path.substring(prefix.length); // Remove rootDir from path + } + }); + + return appFiles; +} + +export function getRootDir(filePaths: string[]): string { + if (!filePaths.length) { + return path.sep; + } + + const splitPaths: string[][] = []; + for (const filePath of filePaths) { splitPaths.push(filePath.split("/").filter(Boolean)); } @@ -37,16 +96,7 @@ export function getAppFilesRootDir( // Join the common parts to form the common directory const rootDir = "/" + commonParts.join("/"); - - // Remove the common path prefix from each appFile - appFiles.forEach((file) => { - const prefix = rootDir === path.sep ? rootDir : `${rootDir}${path.sep}`; - if (file.path.startsWith(prefix)) { - file.path = file.path.substring(prefix.length); // Remove rootDir from path - } - }); - - return [rootDir || path.sep, appFiles]; + return rootDir || path.sep; } export function getApplicationFiles( @@ -56,9 +106,14 @@ export function getApplicationFiles( ): AppDepsScanResultWithoutTarget[] { const scanResults: AppDepsScanResultWithoutTarget[] = []; - const [appFilesRootDir, appFiles] = getAppFilesRootDir( - Object.keys(filePathToContent), + const manifestMetadataExtractor = filesMetadataExtractorPerLanguage[language]; + const appFilesRootDir = getRootDir(Object.keys(filePathToContent)); + const appFiles = getAppFileInfos( + filePathToContent, + appFilesRootDir, + manifestMetadataExtractor, ); + if (appFiles.length) { scanResults.push({ facts: [ diff --git a/lib/analyzer/applications/types.ts b/lib/analyzer/applications/types.ts index b3597d1a..6c6fc78c 100644 --- a/lib/analyzer/applications/types.ts +++ b/lib/analyzer/applications/types.ts @@ -33,10 +33,14 @@ export interface AggregatedJars { } export interface ApplicationFileInfo { path: string; + type?: "Manifest" | "Code"; + metadata?: { + repoUrl?: string; + moduleName?: string; + }; } export interface ApplicationFiles { fileHierarchy: ApplicationFileInfo[]; - moduleName?: string; language: string; } diff --git a/test/lib/analyzer/runtime-commons.spec.ts b/test/lib/analyzer/runtime-commons.spec.ts new file mode 100644 index 00000000..3bde8e50 --- /dev/null +++ b/test/lib/analyzer/runtime-commons.spec.ts @@ -0,0 +1,170 @@ +import { + filesMetadataExtractorPerLanguage, + getAppFileInfos, + getRootDir, +} from "../../../lib/analyzer/applications/runtime-common"; + +describe("application files root dir extraction", () => { + it("should correctly get root dir for js ts files", async () => { + let nodeProjectFiles = [ + "/aaa/bbb/ccc/y.js", + "/aaa/bbb/ccc/z.js", + "/aaa/x.js", + ]; + + expect(getRootDir(nodeProjectFiles)).toBe("/aaa"); + + nodeProjectFiles = [ + "/srv/dist/index.js", + "/srv/dist/src/app.js", + "/srv/dist/src/utils/helpers.js", + "/srv/dist/src/components/header.ts", + "/srv/dist/src/components/footer.js", + "/srv/dist/src/services/api.js", + "/srv/dist/src/models/user.js", + "/srv/dist/src/config/config.ts", + "/srv/dist/package.json", + "/srv/dist/package-lock.json", + ]; + + expect(getRootDir(nodeProjectFiles)).toBe("/srv/dist"); + }); + + it("should return / as the root dir in case nothing's found", async () => { + const nodeProjectFiles = ["/srv/dist/index.js", "/opt/app.js"]; + expect(getRootDir(nodeProjectFiles)).toBe("/"); + }); + + it("should only consider full path segments for common prefix", async () => { + const nodeProjectFiles = ["/srv/dist/index.js", "/srv2/app.js"]; + expect(getRootDir(nodeProjectFiles)).toBe("/"); + }); + + it("should correctly get root dir for python application files", async () => { + const pythonProjectFiles = [ + "/app/index.py", + "/app/src/app.py", + "/app/src/utils/helpers.py", + "/app/src/components/header.py", + "/app/src/components/footer.py", + "/app/src/services/api.py", + "/app/src/models/user.py", + "/app/src/config/config.py", + "/app/requirements.txt", + ]; + expect(getRootDir(pythonProjectFiles)).toBe("/app"); + }); +}); + +describe("application files info extraction", () => { + it("should correctly get app infos for js ts files", async () => { + const nodeProjectFiles = { + "/aaa/bbb/ccc/y.js": "", + "/aaa/bbb/ccc/z.js": "", + "/aaa/x.js": "", + }; + + const appFiles = getAppFileInfos( + nodeProjectFiles, + "/aaa", + filesMetadataExtractorPerLanguage.node, + ); + expect(appFiles.length).toBe(3); + expect(appFiles).toEqual([ + { path: "bbb/ccc/y.js" }, + { path: "bbb/ccc/z.js" }, + { path: "x.js" }, + ]); + }); + + it("should correctly identify node manifest files", async () => { + const nodeProjectFiles = { + "/srv/dist/index.js": "", + "/srv/dist/src/app.js": "", + "/srv/dist/src/utils/helpers.js": "", + "/srv/dist/src/components/header.ts": "", + "/srv/dist/src/components/footer.js": "", + "/srv/dist/src/services/api.js": "", + "/srv/dist/src/models/user.js": "", + "/srv/dist/src/config/config.ts": "", + "/srv/dist/package.json": "{}", + "/srv/dist/package-lock.json": "{}", + }; + + const appFiles = getAppFileInfos( + nodeProjectFiles, + "/srv/dist", + filesMetadataExtractorPerLanguage.node, + ); + expect(appFiles.length).toBe(10); + expect(appFiles).toEqual([ + { path: "index.js" }, + { path: "src/app.js" }, + { path: "src/utils/helpers.js" }, + { path: "src/components/header.ts" }, + { path: "src/components/footer.js" }, + { path: "src/services/api.js" }, + { path: "src/models/user.js" }, + { path: "src/config/config.ts" }, + { + path: "package.json", + type: "Manifest", + metadata: { moduleName: "package.json" }, + }, + { + path: "package-lock.json", + type: "Manifest", + metadata: { moduleName: "package.json" }, + }, + ]); + }); + + it("should not change app files path when root dir is /", async () => { + const nodeProjectFiles = { + "/srv/dist/index.js": "", + "/opt/app.js": "", + }; + const appFiles = getAppFileInfos( + nodeProjectFiles, + "/", + filesMetadataExtractorPerLanguage.node, + ); + expect(appFiles.length).toBe(2); + expect(appFiles).toEqual([ + { path: "srv/dist/index.js" }, + { path: "opt/app.js" }, + ]); + }); + + it("should correctly get app infos for python files", async () => { + const pythonProjectFiles = { + "/app/index.py": "", + "/app/src/app.py": "", + "/app/src/utils/helpers.py": "", + "/app/src/components/header.py": "", + "/app/src/components/footer.py": "", + "/app/src/services/api.py": "", + "/app/src/models/user.py": "", + "/app/src/config/config.py": "", + "/app/requirements.txt": "", + }; + const appFiles = getAppFileInfos( + pythonProjectFiles, + "/app", + filesMetadataExtractorPerLanguage.python, + ); + + expect(appFiles.length).toBe(9); + expect(appFiles).toEqual([ + { path: "index.py" }, + { path: "src/app.py" }, + { path: "src/utils/helpers.py" }, + { path: "src/components/header.py" }, + { path: "src/components/footer.py" }, + { path: "src/services/api.py" }, + { path: "src/models/user.py" }, + { path: "src/config/config.py" }, + { path: "requirements.txt" }, + ]); + }); +}); diff --git a/test/system/application-scans/node.spec.ts b/test/system/application-scans/node.spec.ts index 44802bfb..aa51d3d8 100644 --- a/test/system/application-scans/node.spec.ts +++ b/test/system/application-scans/node.spec.ts @@ -10,7 +10,6 @@ import { shouldBuildDepTree, } from "../../../lib/analyzer/applications/node"; import * as nodeUtils from "../../../lib/analyzer/applications/node-modules-utils"; -import { getAppFilesRootDir } from "../../../lib/analyzer/applications/runtime-common"; import { FilePathToContent } from "../../../lib/analyzer/applications/types"; import { getFixture, getObjFromFixture } from "../../util"; @@ -179,7 +178,11 @@ describe("node application scans", () => { { path: "bin/yarn.js" }, { path: "lib/cli.js" }, { path: "lib/v8-compile-cache.js" }, - { path: "package.json" }, + { + path: "package.json", + type: "Manifest", + metadata: { moduleName: "yarn" }, + }, ]); }); @@ -661,73 +664,6 @@ describe("node application files grouping", () => { "/opt/local/lib", ]); }); - - it("should correctly group js ts files with root dir", async () => { - let nodeProjectFiles = [ - "/aaa/bbb/ccc/y.js", - "/aaa/bbb/ccc/z.js", - "/aaa/x.js", - ]; - - let [appFilesRootDir, appFiles] = getAppFilesRootDir(nodeProjectFiles); - - expect(appFilesRootDir).toBe("/aaa"); - expect(appFiles.length).toBe(3); - - nodeProjectFiles = [ - "/srv/dist/index.js", - "/srv/dist/src/app.js", - "/srv/dist/src/utils/helpers.js", - "/srv/dist/src/components/header.ts", - "/srv/dist/src/components/footer.js", - "/srv/dist/src/services/api.js", - "/srv/dist/src/models/user.js", - "/srv/dist/src/config/config.ts", - "/srv/dist/package.json", - "/srv/dist/package-lock.json", - ]; - - [appFilesRootDir, appFiles] = getAppFilesRootDir(nodeProjectFiles); - - expect(appFilesRootDir).toBe("/srv/dist"); - expect(appFiles.length).toBe(10); - expect(appFiles).toEqual([ - { path: "index.js" }, - { path: "src/app.js" }, - { path: "src/utils/helpers.js" }, - { path: "src/components/header.ts" }, - { path: "src/components/footer.js" }, - { path: "src/services/api.js" }, - { path: "src/models/user.js" }, - { path: "src/config/config.ts" }, - { path: "package.json" }, - { path: "package-lock.json" }, - ]); - }); - - it("should return / as the root dir in case nothing's found", async () => { - const nodeProjectFiles = ["/srv/dist/index.js", "/opt/app.js"]; - - const [appFilesRootDir, appFiles] = getAppFilesRootDir(nodeProjectFiles); - expect(appFilesRootDir).toBe("/"); - expect(appFiles.length).toBe(2); - expect(appFiles).toEqual([ - { path: "srv/dist/index.js" }, - { path: "opt/app.js" }, - ]); - }); - - it("should only consider full path segments for common prefix", async () => { - const nodeProjectFiles = ["/srv/dist/index.js", "/srv2/app.js"]; - - const [appFilesRootDir, appFiles] = getAppFilesRootDir(nodeProjectFiles); - expect(appFilesRootDir).toBe("/"); - expect(appFiles.length).toBe(2); - expect(appFiles).toEqual([ - { path: "srv/dist/index.js" }, - { path: "srv2/app.js" }, - ]); - }); }); describe("Edge testing of node modules scan utils functions", () => { diff --git a/test/system/application-scans/python/pip.spec.ts b/test/system/application-scans/python/pip.spec.ts index d1c57caa..36191eba 100644 --- a/test/system/application-scans/python/pip.spec.ts +++ b/test/system/application-scans/python/pip.spec.ts @@ -1,5 +1,4 @@ import { scan } from "../../../../lib"; -import { getAppFilesRootDir } from "../../../../lib/analyzer/applications/runtime-common"; import { getFixture } from "../../../util"; describe("pip application scan", () => { @@ -83,34 +82,3 @@ describe("pip application scan", () => { expect(appFiles[0].fileHierarchy).toStrictEqual([{ path: "server.py" }]); }); }); - -describe("python application files filtering", () => { - it("should correctly filter python application files", async () => { - const pythonProjectFiles = [ - "/app/index.py", - "/app/src/app.py", - "/app/src/utils/helpers.py", - "/app/src/components/header.py", - "/app/src/components/footer.py", - "/app/src/services/api.py", - "/app/src/models/user.py", - "/app/src/config/config.py", - "/app/requirements.txt", - ]; - const [appFilesRootDir, appFiles] = getAppFilesRootDir(pythonProjectFiles); - - expect(appFilesRootDir).toBe("/app"); - expect(appFiles.length).toBe(9); - expect(appFiles).toEqual([ - { path: "index.py" }, - { path: "src/app.py" }, - { path: "src/utils/helpers.py" }, - { path: "src/components/header.py" }, - { path: "src/components/footer.py" }, - { path: "src/services/api.py" }, - { path: "src/models/user.py" }, - { path: "src/config/config.py" }, - { path: "requirements.txt" }, - ]); - }); -}); From 7ec6fbde434e31812453bb28b33066edd02d791f Mon Sep 17 00:00:00 2001 From: natashz Date: Wed, 8 Jan 2025 12:06:59 +0200 Subject: [PATCH 2/5] fix: pr comments --- lib/analyzer/applications/runtime-common.ts | 47 +++++++++++++-------- lib/analyzer/applications/types.ts | 18 +++++--- test/lib/analyzer/runtime-commons.spec.ts | 8 ++-- test/system/application-scans/node.spec.ts | 7 ++- 4 files changed, 52 insertions(+), 28 deletions(-) diff --git a/lib/analyzer/applications/runtime-common.ts b/lib/analyzer/applications/runtime-common.ts index 76834dc7..83dab5dc 100644 --- a/lib/analyzer/applications/runtime-common.ts +++ b/lib/analyzer/applications/runtime-common.ts @@ -3,13 +3,16 @@ import { parsePkgJson } from "snyk-nodejs-lockfile-parser"; import { ApplicationFilesFact } from "../../facts"; import { AppDepsScanResultWithoutTarget, + AppFileType, ApplicationFileInfo, FilePathToContent, + ManifestMetadata, } from "./types"; +import { bool } from "aws-sdk/clients/signer"; interface AppFileMetadataExtractor { - manifestFiles: string[]; - metadataExtractor: (fileContent: string) => Record; + manifestFileMatcher: (filePath: string) => bool; + metadataExtractor: (fileContent: string) => ManifestMetadata | undefined; } export const filesMetadataExtractorPerLanguage: Record< @@ -17,14 +20,25 @@ export const filesMetadataExtractorPerLanguage: Record< AppFileMetadataExtractor > = { node: { - manifestFiles: ["package.json", "package-lock.json", "yarn.lock"], + manifestFileMatcher: (filePath: string) => { + return ["package.json", "package-lock.json", "yarn.lock"].some( + (mf) => path.basename(filePath) === mf, + ); + }, metadataExtractor: (fileContent: string) => { - const pkgJson = parsePkgJson(fileContent); - const repoUrl = (pkgJson as any).repository?.url; - return { - moduleName: pkgJson.name, - repoUrl, - }; + try { + const pkgJson = parsePkgJson(fileContent); + const metadata: ManifestMetadata = { + moduleName: pkgJson.name, + }; + const repoUrl = (pkgJson as any).repository?.url; + if (repoUrl) { + metadata.repoUrl = repoUrl; + } + return metadata; + } catch (err) { + return undefined; + } }, }, }; @@ -44,14 +58,11 @@ export function getAppFileInfos( for (const filePath of filePaths) { const appFile: ApplicationFileInfo = { path: filePath }; if (manifestMetadataExtractor) { - const { manifestFiles, metadataExtractor } = manifestMetadataExtractor; - if ( - manifestFiles.length && - manifestFiles.some((mf) => filePath.endsWith("/" + mf)) - ) { - appFile.type = "Manifest"; + const { manifestFileMatcher, metadataExtractor } = + manifestMetadataExtractor; + if (manifestFileMatcher(filePath)) { + appFile.type = AppFileType.Manifest; const manifestContent = filePathToContent[filePath]; - appFile.metadata = metadataExtractor(manifestContent); } } @@ -61,7 +72,9 @@ export function getAppFileInfos( // Remove the common path prefix from each appFile appFiles.forEach((file) => { - const prefix = rootDir === path.sep ? rootDir : `${rootDir}${path.sep}`; + const prefix = rootDir.endsWith(path.sep) + ? rootDir + : `${rootDir}${path.sep}`; if (file.path.startsWith(prefix)) { file.path = file.path.substring(prefix.length); // Remove rootDir from path } diff --git a/lib/analyzer/applications/types.ts b/lib/analyzer/applications/types.ts index 6c6fc78c..80c4fd2c 100644 --- a/lib/analyzer/applications/types.ts +++ b/lib/analyzer/applications/types.ts @@ -31,13 +31,21 @@ export interface FilePathToElfContent { export interface AggregatedJars { [path: string]: JarBuffer[]; } + +export interface ManifestMetadata { + repoUrl?: string; + moduleName?: string; +} + +export enum AppFileType { + Manifest = "manifest", + Code = "code", +} + export interface ApplicationFileInfo { path: string; - type?: "Manifest" | "Code"; - metadata?: { - repoUrl?: string; - moduleName?: string; - }; + type?: AppFileType; + metadata?: ManifestMetadata; } export interface ApplicationFiles { fileHierarchy: ApplicationFileInfo[]; diff --git a/test/lib/analyzer/runtime-commons.spec.ts b/test/lib/analyzer/runtime-commons.spec.ts index 3bde8e50..858597df 100644 --- a/test/lib/analyzer/runtime-commons.spec.ts +++ b/test/lib/analyzer/runtime-commons.spec.ts @@ -3,6 +3,7 @@ import { getAppFileInfos, getRootDir, } from "../../../lib/analyzer/applications/runtime-common"; +import { AppFileType } from "../../../lib/analyzer/applications/types"; describe("application files root dir extraction", () => { it("should correctly get root dir for js ts files", async () => { @@ -88,7 +89,7 @@ describe("application files info extraction", () => { "/srv/dist/src/models/user.js": "", "/srv/dist/src/config/config.ts": "", "/srv/dist/package.json": "{}", - "/srv/dist/package-lock.json": "{}", + "/srv/dist/package-lock.json": "{", // check that we do not fail bad formatted files. }; const appFiles = getAppFileInfos( @@ -108,13 +109,12 @@ describe("application files info extraction", () => { { path: "src/config/config.ts" }, { path: "package.json", - type: "Manifest", + type: AppFileType.Manifest, metadata: { moduleName: "package.json" }, }, { path: "package-lock.json", - type: "Manifest", - metadata: { moduleName: "package.json" }, + type: AppFileType.Manifest, }, ]); }); diff --git a/test/system/application-scans/node.spec.ts b/test/system/application-scans/node.spec.ts index aa51d3d8..bfd29786 100644 --- a/test/system/application-scans/node.spec.ts +++ b/test/system/application-scans/node.spec.ts @@ -10,7 +10,10 @@ import { shouldBuildDepTree, } from "../../../lib/analyzer/applications/node"; import * as nodeUtils from "../../../lib/analyzer/applications/node-modules-utils"; -import { FilePathToContent } from "../../../lib/analyzer/applications/types"; +import { + AppFileType, + FilePathToContent, +} from "../../../lib/analyzer/applications/types"; import { getFixture, getObjFromFixture } from "../../util"; describe("node application scans", () => { @@ -180,7 +183,7 @@ describe("node application scans", () => { { path: "lib/v8-compile-cache.js" }, { path: "package.json", - type: "Manifest", + type: AppFileType.Manifest, metadata: { moduleName: "yarn" }, }, ]); From 651b58d0b059cd7e3f6cedd27a5195a2eb00ca51 Mon Sep 17 00:00:00 2001 From: natashz Date: Wed, 8 Jan 2025 12:07:41 +0200 Subject: [PATCH 3/5] fix: pr comments2 --- lib/analyzer/applications/runtime-common.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/analyzer/applications/runtime-common.ts b/lib/analyzer/applications/runtime-common.ts index 83dab5dc..2df97726 100644 --- a/lib/analyzer/applications/runtime-common.ts +++ b/lib/analyzer/applications/runtime-common.ts @@ -8,10 +8,9 @@ import { FilePathToContent, ManifestMetadata, } from "./types"; -import { bool } from "aws-sdk/clients/signer"; interface AppFileMetadataExtractor { - manifestFileMatcher: (filePath: string) => bool; + manifestFileMatcher: (filePath: string) => boolean; metadataExtractor: (fileContent: string) => ManifestMetadata | undefined; } From cc5e48e35663fd356803f30eed9e963a149098e4 Mon Sep 17 00:00:00 2001 From: natashz Date: Wed, 8 Jan 2025 13:06:30 +0200 Subject: [PATCH 4/5] fix: pr comments3 --- lib/analyzer/applications/node-modules-utils.ts | 3 ++- lib/analyzer/applications/runtime-common.ts | 13 +++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/analyzer/applications/node-modules-utils.ts b/lib/analyzer/applications/node-modules-utils.ts index a986e374..3d73b92f 100644 --- a/lib/analyzer/applications/node-modules-utils.ts +++ b/lib/analyzer/applications/node-modules-utils.ts @@ -34,7 +34,8 @@ async function createTempProjectDir( }; } -const manifestName: string = "package.json"; +export const manifestName: string = "package.json"; +export const manifestLockName: string = "package-lock.json"; async function fileExists(path: string): Promise { return await stat(path) diff --git a/lib/analyzer/applications/runtime-common.ts b/lib/analyzer/applications/runtime-common.ts index 2df97726..ea7ca067 100644 --- a/lib/analyzer/applications/runtime-common.ts +++ b/lib/analyzer/applications/runtime-common.ts @@ -8,6 +8,10 @@ import { FilePathToContent, ManifestMetadata, } from "./types"; +import { + manifestLockName as nodeManifestLockName, + manifestName as nodeManifestName, +} from "./node-modules-utils"; interface AppFileMetadataExtractor { manifestFileMatcher: (filePath: string) => boolean; @@ -20,17 +24,22 @@ export const filesMetadataExtractorPerLanguage: Record< > = { node: { manifestFileMatcher: (filePath: string) => { - return ["package.json", "package-lock.json", "yarn.lock"].some( + return [nodeManifestName, nodeManifestLockName].some( (mf) => path.basename(filePath) === mf, ); }, metadataExtractor: (fileContent: string) => { try { const pkgJson = parsePkgJson(fileContent); + const moduleName = pkgJson.name; + const repoUrl = (pkgJson as any).repository?.url; + + if (!repoUrl && !moduleName) { + return undefined; + } const metadata: ManifestMetadata = { moduleName: pkgJson.name, }; - const repoUrl = (pkgJson as any).repository?.url; if (repoUrl) { metadata.repoUrl = repoUrl; } From 9552f4b7377520b4f660e82ca703539a23b090c1 Mon Sep 17 00:00:00 2001 From: natashz Date: Wed, 8 Jan 2025 13:12:52 +0200 Subject: [PATCH 5/5] fix: lineter --- lib/analyzer/applications/runtime-common.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/analyzer/applications/runtime-common.ts b/lib/analyzer/applications/runtime-common.ts index ea7ca067..12883b64 100644 --- a/lib/analyzer/applications/runtime-common.ts +++ b/lib/analyzer/applications/runtime-common.ts @@ -1,6 +1,10 @@ import * as path from "path"; import { parsePkgJson } from "snyk-nodejs-lockfile-parser"; import { ApplicationFilesFact } from "../../facts"; +import { + manifestLockName as nodeManifestLockName, + manifestName as nodeManifestName, +} from "./node-modules-utils"; import { AppDepsScanResultWithoutTarget, AppFileType, @@ -8,10 +12,6 @@ import { FilePathToContent, ManifestMetadata, } from "./types"; -import { - manifestLockName as nodeManifestLockName, - manifestName as nodeManifestName, -} from "./node-modules-utils"; interface AppFileMetadataExtractor { manifestFileMatcher: (filePath: string) => boolean;