From 48e3995b725d991117fa4f9266084ae5c7d5653a Mon Sep 17 00:00:00 2001 From: Brian Gardiner Date: Wed, 3 Dec 2025 09:29:56 -0500 Subject: [PATCH] fix: use correct projectName in container monitor JSON output The projectName field in 'snyk container monitor --json' output was incorrectly set to monitorResult.id (the monitor's public ID) instead of monitorResult.projectName (the actual project name). This caused the JSON output to display a UUID instead of the project's display name (e.g., the image name or --project-name value). Changes: - Fixed src/lib/ecosystems/monitor.ts line 214 to use monitorResult.projectName - Added unit test with mocked registry response to validate the fix - Updated acceptance tests with correct expected projectName values --- src/lib/ecosystems/monitor.ts | 2 +- .../container-deb-scan-result.json | 27 +++++++++++ ...pendencies-response-with-project-name.json | 12 +++++ .../snyk-container/container.spec.ts | 19 +++++++- .../unit/ecosystems-monitor-docker.spec.ts | 48 +++++++++++++++++++ 5 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 test/fixtures/container-projects/container-deb-scan-result.json create mode 100644 test/fixtures/container-projects/monitor-dependencies-response-with-project-name.json diff --git a/src/lib/ecosystems/monitor.ts b/src/lib/ecosystems/monitor.ts index 929bc088b7..30821f1169 100644 --- a/src/lib/ecosystems/monitor.ts +++ b/src/lib/ecosystems/monitor.ts @@ -218,7 +218,7 @@ export async function getFormattedMonitorOutput( ok: true, data: monOutput, path: monitorResult.path, - projectName: monitorResult.id, + projectName: monitorResult.projectName, }); } for (const monitorError of errors) { diff --git a/test/fixtures/container-projects/container-deb-scan-result.json b/test/fixtures/container-projects/container-deb-scan-result.json new file mode 100644 index 0000000000..25b4ffff93 --- /dev/null +++ b/test/fixtures/container-projects/container-deb-scan-result.json @@ -0,0 +1,27 @@ +{ + "identity": { + "type": "deb" + }, + "facts": [ + { + "type": "depGraph", + "data": { + "schemaVersion": "1.2.0", + "pkgManager": { + "name": "deb", + "repositories": [{"alias": "debian:11"}] + }, + "pkgs": [{"id": "alpine@3.18", "info": {"name": "alpine", "version": "3.18"}}], + "graph": { + "rootNodeId": "root-node", + "nodes": [{"nodeId": "root-node", "pkgId": "alpine@3.18", "deps": []}] + } + } + } + ], + "target": { + "image": "alpine:latest" + }, + "name": "my-custom-project-name" +} + diff --git a/test/fixtures/container-projects/monitor-dependencies-response-with-project-name.json b/test/fixtures/container-projects/monitor-dependencies-response-with-project-name.json new file mode 100644 index 0000000000..086f7c1783 --- /dev/null +++ b/test/fixtures/container-projects/monitor-dependencies-response-with-project-name.json @@ -0,0 +1,12 @@ +{ + "ok": true, + "org": "test-org", + "id": "7c7305e2-fbcb-44d7-8fbf-8367371c509f", + "isMonitored": true, + "licensesPolicy": null, + "uri": "https://app.snyk.io/org/test-org/project/3dda9b21-ca42-4de6-be7a-85696fa6e866/history/f60dce17-8a72-4cca-8a76-e9c88df546aa", + "trialStarted": false, + "path": "/srv", + "projectName": "my-custom-project-name" +} + diff --git a/test/jest/acceptance/snyk-container/container.spec.ts b/test/jest/acceptance/snyk-container/container.spec.ts index 478111e1cb..2e23878c0b 100644 --- a/test/jest/acceptance/snyk-container/container.spec.ts +++ b/test/jest/acceptance/snyk-container/container.spec.ts @@ -18,8 +18,8 @@ describe('snyk container', () => { }); } - const TEST_DISTROLESS_STATIC_IMAGE = - 'gcr.io/distroless/static@sha256:7198a357ff3a8ef750b041324873960cf2153c11cc50abb9d8d5f8bb089f6b4e'; + const TEST_DISTROLESS_STATIC_IMAGE_NAME = 'gcr.io/distroless/static'; + const TEST_DISTROLESS_STATIC_IMAGE = `${TEST_DISTROLESS_STATIC_IMAGE_NAME}@sha256:7198a357ff3a8ef750b041324873960cf2153c11cc50abb9d8d5f8bb089f6b4e`; const TEST_DISTROLESS_STATIC_IMAGE_DEPGRAPH = { schemaVersion: '1.3.0', pkgManager: { @@ -612,6 +612,7 @@ DepGraph end`, expect.objectContaining({ ok: true, packageManager: 'deb', + projectName: `docker-image|${TEST_DISTROLESS_STATIC_IMAGE_NAME}`, manageUrl: expect.stringContaining('://'), scanResult: expect.objectContaining({ facts: expect.arrayContaining([ @@ -646,6 +647,7 @@ DepGraph end`, expect.objectContaining({ ok: true, packageManager: 'deb', + projectName: 'docker-image|snyk/snyk', manageUrl: expect.stringContaining('://'), scanResult: expect.objectContaining({ facts: expect.arrayContaining([ @@ -668,6 +670,7 @@ DepGraph end`, expect.objectContaining({ ok: true, packageManager: 'gomodules', + projectName: 'docker-image|snyk/snyk:/usr/local/bin/snyk', manageUrl: expect.stringContaining('://'), scanResult: expect.objectContaining({ facts: expect.arrayContaining([ @@ -685,6 +688,18 @@ DepGraph end`, ]), ); }); + + it('snyk container monitor json returns custom projectName when --project-name is provided', async () => { + const customProjectName = 'my-custom-project-name'; + const { code, stdout } = await runSnykCLI( + `container monitor --platform=linux/amd64 --project-name=${customProjectName} --json ${TEST_DISTROLESS_STATIC_IMAGE}`, + ); + expect(code).toEqual(0); + const result = JSON.parse(stdout); + + // projectName should match the --project-name flag value + expect(result.projectName).toBe(customProjectName); + }); }); describe('snyk container monitor supports --target-reference', () => { diff --git a/test/jest/unit/ecosystems-monitor-docker.spec.ts b/test/jest/unit/ecosystems-monitor-docker.spec.ts index 1fbcb57776..757873ca5e 100644 --- a/test/jest/unit/ecosystems-monitor-docker.spec.ts +++ b/test/jest/unit/ecosystems-monitor-docker.spec.ts @@ -186,4 +186,52 @@ describe('monitorEcosystem docker/container', () => { makeRequestSpy.mock.calls[0][0].body.pruneRepeatedSubdependencies, ).toBeUndefined(); }); + + it('should return projectName from registry response in JSON output', async () => { + const containerScanResult = readJsonFixture( + 'container-deb-scan-result.json', + ) as ScanResult; + const monitorDependenciesResponse = readJsonFixture( + 'monitor-dependencies-response-with-project-name.json', + ) as ecosystemsTypes.MonitorDependenciesResponse; + + jest + .spyOn(dockerPlugin, 'scan') + .mockResolvedValue({ scanResults: [containerScanResult] }); + jest + .spyOn(request, 'makeRequest') + .mockResolvedValue(monitorDependenciesResponse); + + const results: Array = []; + + const [monitorResults, monitorErrors] = await ecosystems.monitorEcosystem( + 'docker', + ['/srv'], + { + path: '/srv', + docker: true, + org: 'test-org', + }, + ); + + const jsonOutput = await getFormattedMonitorOutput( + results, + monitorResults, + monitorErrors, + { + path: '/srv', + docker: true, + org: 'test-org', + json: true, + } as Options, + ); + + const parsedOutput = JSON.parse(jsonOutput); + + // projectName should be the actual project name from the registry, not the id (UUID) + expect(parsedOutput.projectName).toBe('my-custom-project-name'); + expect(parsedOutput.projectName).not.toBe( + '7c7305e2-fbcb-44d7-8fbf-8367371c509f', + ); + }); });