From 5baff2dc4905a2c00c34ef747eb6812c2dfe6aa5 Mon Sep 17 00:00:00 2001 From: Erlend Oftedal Date: Thu, 4 Jul 2024 15:59:08 +0200 Subject: [PATCH] Remove duplicate filenames in CycloneDX JSON output --- chrome/extension/js/generated/retire-chrome.js | 2 +- node/CHANGELOG.md | 8 +++++++- node/lib/retire.js | 2 +- node/package-lock.json | 4 ++-- node/package.json | 2 +- node/src/reporters/cyclonedx-1_6-json.ts | 8 ++++++-- node/src/reporters/cyclonedx-json.ts | 18 ++++++++++++++---- 7 files changed, 32 insertions(+), 12 deletions(-) diff --git a/chrome/extension/js/generated/retire-chrome.js b/chrome/extension/js/generated/retire-chrome.js index 0567a4f7..c738b5f4 100644 --- a/chrome/extension/js/generated/retire-chrome.js +++ b/chrome/extension/js/generated/retire-chrome.js @@ -50,7 +50,7 @@ function deepScan(content, repo) { */ var exports = exports || {}; -exports.version = '5.1.0'; +exports.version = '5.1.1'; function isDefined(o) { return typeof o !== 'undefined'; diff --git a/node/CHANGELOG.md b/node/CHANGELOG.md index 1ccb8231..6b24a08a 100644 --- a/node/CHANGELOG.md +++ b/node/CHANGELOG.md @@ -1,8 +1,14 @@ # Changelog +## [5.1.1] + +### Bugfix + +- Remove duplicates in filename output in CycloneDX JSON formats + ## [5.1.0] -## Add +### Add - Support for CycloneDX 1.6 JSON as output format - Adding file location as property in CycloneDX 1.4 JSON output diff --git a/node/lib/retire.js b/node/lib/retire.js index 47c739d7..49ee7413 100644 --- a/node/lib/retire.js +++ b/node/lib/retire.js @@ -4,7 +4,7 @@ */ var exports = exports || {}; -exports.version = '5.1.0'; +exports.version = '5.1.1'; function isDefined(o) { return typeof o !== 'undefined'; diff --git a/node/package-lock.json b/node/package-lock.json index 68a5388e..beb9ef59 100644 --- a/node/package-lock.json +++ b/node/package-lock.json @@ -1,12 +1,12 @@ { "name": "retire", - "version": "5.1.0", + "version": "5.1.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "retire", - "version": "5.1.0", + "version": "5.1.1", "license": "Apache-2.0", "dependencies": { "ansi-colors": "^4.1.1", diff --git a/node/package.json b/node/package.json index 014ed474..b42849c3 100644 --- a/node/package.json +++ b/node/package.json @@ -2,7 +2,7 @@ "author": "Erlend Oftedal ", "name": "retire", "description": "Retire is a tool for detecting use of vulnerable libraries", - "version": "5.1.0", + "version": "5.1.1", "license": "Apache-2.0", "repository": { "type": "git", diff --git a/node/src/reporters/cyclonedx-1_6-json.ts b/node/src/reporters/cyclonedx-1_6-json.ts index 83598732..0e0ab08d 100644 --- a/node/src/reporters/cyclonedx-1_6-json.ts +++ b/node/src/reporters/cyclonedx-1_6-json.ts @@ -63,8 +63,12 @@ function configureCycloneDXJSONLogger(logger: Logger, writer: Writer, config: Lo ]; } const purl = generatePURL(dep); - if (seen.has(purl)) { - seen.get(purl)?.evidence.occurrences.push(...evidence.occurrences); + const existing = seen.get(purl); + if (existing) { + const missing = evidence.occurrences.filter( + (x) => !existing.evidence.occurrences.some((y) => y.location == x.location), + ); + existing.evidence.occurrences.push(...missing); return undefined; } const result = { diff --git a/node/src/reporters/cyclonedx-json.ts b/node/src/reporters/cyclonedx-json.ts index e6f96723..9226429b 100644 --- a/node/src/reporters/cyclonedx-json.ts +++ b/node/src/reporters/cyclonedx-json.ts @@ -33,9 +33,13 @@ function configureCycloneDXJSONLogger(logger: Logger, writer: Writer, config: Lo } }; + type Component = { + properties: Array<{ name: string; value: string }>; + }; + logger.close = function (callback) { const write = vulnsFound ? writer.err : writer.out; - const seen = new Set(); + const seen = new Map(); const components = finalResults.data .filter((d) => d.results) .map((r) => @@ -57,9 +61,13 @@ function configureCycloneDXJSONLogger(logger: Logger, writer: Writer, config: Lo ]; } const purl = generatePURL(dep); - if (seen.has(purl)) return undefined; - seen.add(purl); - return { + const existing = seen.get(purl); + if (existing) { + const missing = properties.filter((p) => !existing.properties.some((ep) => ep.value === p.value)); + existing.properties.push(...missing); + return undefined; + } + const result = { type: 'library', name: dep.component, version: dep.version, @@ -67,6 +75,8 @@ function configureCycloneDXJSONLogger(logger: Logger, writer: Writer, config: Lo hashes: hashes, properties, }; + seen.set(purl, result); + return result; }) .filter((x) => x != undefined), )