diff --git a/.gitignore b/.gitignore index 456199a..4610a1a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ node_modules dust dist/ .devcontainer +tmp/ \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 4057531..34e6e67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ ### Enhancement +* Include licenses in SBOM output + +## 1.5.0 + +### Enhancement + * Improve CycloneDX vulnerability IDs ## 1.4.1 diff --git a/package-lock.json b/package-lock.json index 9738dcc..561241b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,17 @@ { "name": "retire-site-scanner", - "version": "1.5.0", + "version": "1.6.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "retire-site-scanner", - "version": "1.5.0", + "version": "1.6.0", "license": "Apache-2.0", "dependencies": { "cacheable-lookup": "^7.0.0", "puppeteer": "^22.4.0", - "retire": "^5.1.4", + "retire": "^5.2.0", "source-map": "^0.7.4" }, "bin": { @@ -2777,9 +2777,9 @@ } }, "node_modules/retire": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/retire/-/retire-5.1.4.tgz", - "integrity": "sha512-PQJ8B6LN7MZgN2CpW+JuiCrdL+O7EyZCNuQCvgw6X8aMfmmeLlMie+jH/0oTHyOC3Ll5fEiRcq1hn2Walw8u2Q==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/retire/-/retire-5.2.0.tgz", + "integrity": "sha512-xKocfNK75RC/QGipVdMrX6MwmHRBRJGo3UHpbMkpREt2PfQVLafFwqREB3l/aR17e3PMIj6IrlDPqak5OPCKJA==", "dependencies": { "ansi-colors": "^4.1.1", "astronomical": "^1.0.0", diff --git a/package.json b/package.json index 76110bd..09eae0b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "author": "Erlend Oftedal ", "name": "retire-site-scanner", - "version": "1.5.0", + "version": "1.6.0", "license": "Apache-2.0", "description": "A scanner for checking a web site using retire.js", "main": "dist/index.js", @@ -24,7 +24,7 @@ "dependencies": { "cacheable-lookup": "^7.0.0", "puppeteer": "^22.4.0", - "retire": "^5.1.4", + "retire": "^5.2.0", "source-map": "^0.7.4" }, "devDependencies": { diff --git a/src/log.ts b/src/log.ts index 5fb0d23..642ee47 100644 --- a/src/log.ts +++ b/src/log.ts @@ -71,6 +71,12 @@ type CycloneDXComponent = { version: string; "bom-ref": string; purl?: string; + licenses?: Array<{ + license?: { + name: string; + }; + expression?: string; + }>; properties: Array<{ name: string; value: string; @@ -196,6 +202,7 @@ export function convertToCycloneDX(resultToConvert: typeof collectedResults) { version: c.version, purl: generatePURL(c), properties: [], + licenses: mapLicenses(c.licenses), }; components.set(key, comp); if (!comp.properties.some((c) => c.value == res.url)) @@ -264,6 +271,14 @@ export function convertToCycloneDX(resultToConvert: typeof collectedResults) { }; } +function mapLicenses(licenses: string[] | undefined) { + if (!licenses) return []; + if (licenses.length == 0) return []; + if (licenses[0] == "commercial") return [{ license: { name: "Commercial" } }]; + return [{ expression: licenses[0] }]; +} + + export const jsonLogger: Logger = { open: (url: string) => { collectedResults.url = url; diff --git a/src/retireWrapper.ts b/src/retireWrapper.ts index 9c95bb8..6def3f1 100644 --- a/src/retireWrapper.ts +++ b/src/retireWrapper.ts @@ -1,5 +1,6 @@ import retire from "retire/lib/retire"; import { deepScan } from "retire/lib/deepscan"; +import { evaluateLicense } from "retire/lib/license"; import { type Repository, type Component } from "retire/lib/types"; import crypto from "crypto"; import log from "./log"; @@ -180,12 +181,31 @@ const scanner = () => loadRetireJSRepo().then( (repo) => ({ - scanUri: (uri: string) => scanUri(repo, uri), + scanUri: (uri: string) => + addLicenses(scanUri(repo, uri), repo.advisories), scanContent: (url: string, contents: string) => - scanContent(repo.advisories, contents, url), - runFuncs: (evaluate: Evaluator) => runFuncs(repo.advisories, evaluate), - scanUrlBackdoored: (url: string) => scanUrlBackdoored(repo, url), + addLicenses( + scanContent(repo.advisories, contents, url), + repo.advisories, + ), + runFuncs: (evaluate: Evaluator) => + runFuncs(repo.advisories, evaluate).then((r) => { + addLicenses(r, repo.advisories); + return r; + }), + scanUrlBackdoored: (url: string) => + addLicenses(scanUrlBackdoored(repo, url), repo.advisories), }) as Scanner, ); +function addLicenses(components: Component[], repo: Repository) { + components.forEach((c) => { + const possibleLicenses = repo[c.component]?.licenses; + if (possibleLicenses) { + c.licenses = evaluateLicense(possibleLicenses, c.version); + } + }); + return components; +} + export default scanner; diff --git a/tests/schematest.ts b/tests/schematest.ts index ac7598a..03a8f20 100644 --- a/tests/schematest.ts +++ b/tests/schematest.ts @@ -17,6 +17,9 @@ describe("cyclonedx-json", () => { "jsf-0.82.schema.json#/definitions/signature", ); const result = validator.validate(cycloneDx, jsonSchema); + if (!result.valid) { + console.log(result.errors); + } expect(result.valid).to.eq(true); }); });