retire 5.4.3 → 5.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/lib/cli.js +1 -1
- package/lib/reporters/cyclonedx-1_6-json.js +21 -3
- package/lib/reporters/cyclonedx-json.js +7 -0
- package/lib/reporters/cyclonedx.js +14 -1
- package/lib/reporters/json.js +2 -0
- package/lib/reporters/utils.d.ts +4 -0
- package/lib/reporters/utils.js +9 -0
- package/lib/reporting.d.ts +1 -1
- package/lib/retire.js +1 -1
- package/package.json +3 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [5.5.0]
|
|
4
|
+
|
|
5
|
+
### Improvements
|
|
6
|
+
|
|
7
|
+
- Include the vulnerability repositories used for the scan in the output: as `vulnerabilityRepositories` in the JSON report, and as `retirejs:vulnerability-repository` entries under `metadata.properties` in all CycloneDX reports.
|
|
8
|
+
- CycloneDX 1.6 VEX output now identifies Retire.js as the source of each vulnerability and rating, including the repository URL when a single repository is used.
|
|
9
|
+
|
|
10
|
+
### Bugfixes
|
|
11
|
+
|
|
12
|
+
- CycloneDX 1.6 VEX output was not schema valid: `ratings[].source` was a string rather than an object, and version ranges were reported as `affects[].range` rather than nested under `affects[].versions[]`.
|
|
13
|
+
|
|
3
14
|
## [5.4.3]
|
|
4
15
|
|
|
5
16
|
* Remove dependencies that are not needed anymore
|
package/lib/cli.js
CHANGED
|
@@ -95,7 +95,7 @@ const scanpath = prg.path ?? prg.jspath ?? '.';
|
|
|
95
95
|
const log = reporting.open({
|
|
96
96
|
colors: !!prg.colors,
|
|
97
97
|
colorwarn,
|
|
98
|
-
jsRepo: jsrepolocation
|
|
98
|
+
jsRepo: jsrepolocation,
|
|
99
99
|
outputformat: prg.outputformat,
|
|
100
100
|
outputpath: prg.outputpath,
|
|
101
101
|
path: scanpath,
|
|
@@ -68,6 +68,12 @@ function configureCycloneDXJSONLogger(logger, writer, config, hash) {
|
|
|
68
68
|
const seen = new Map();
|
|
69
69
|
const vulnerabilitiesCyclone = new Map();
|
|
70
70
|
const includeVEX = config.outputformat === 'cyclonedxJSON1_6_VEX';
|
|
71
|
+
const repositories = (0, utils_1.vulnerabilityRepositories)(config.jsRepo);
|
|
72
|
+
// Only attributable to a single URL when exactly one repository was used
|
|
73
|
+
const retireSource = {
|
|
74
|
+
name: 'Retire.js',
|
|
75
|
+
url: repositories.length === 1 ? repositories[0] : undefined,
|
|
76
|
+
};
|
|
71
77
|
const components = finalResults.data
|
|
72
78
|
.filter((d) => d.results)
|
|
73
79
|
.map((r) => r.results
|
|
@@ -106,13 +112,14 @@ function configureCycloneDXJSONLogger(logger, writer, config, hash) {
|
|
|
106
112
|
const { references, advisories } = mapUrls(vuln);
|
|
107
113
|
vulnerabilitiesCyclone.set(id, {
|
|
108
114
|
id,
|
|
115
|
+
source: retireSource,
|
|
109
116
|
cwes: vuln.cwe.map((c) => parseInt(c.split("-")[1])),
|
|
110
117
|
description: vuln.identifiers.summary,
|
|
111
118
|
advisories: advisories,
|
|
112
119
|
references: references,
|
|
113
120
|
ratings: [
|
|
114
121
|
{
|
|
115
|
-
source:
|
|
122
|
+
source: retireSource,
|
|
116
123
|
severity: vuln.severity,
|
|
117
124
|
},
|
|
118
125
|
],
|
|
@@ -121,8 +128,13 @@ function configureCycloneDXJSONLogger(logger, writer, config, hash) {
|
|
|
121
128
|
}
|
|
122
129
|
vulnerabilitiesCyclone.get(id).affects.push({
|
|
123
130
|
ref: bomRef,
|
|
124
|
-
|
|
125
|
-
|
|
131
|
+
versions: [
|
|
132
|
+
{
|
|
133
|
+
// "vers:npm/1.2.3|>=2.0.0|<5.0.0"
|
|
134
|
+
range: 'vers:npm/' + (vuln.atOrAbove ? '>=' + vuln.atOrAbove + '|' : '') + '<' + vuln.below,
|
|
135
|
+
status: 'affected',
|
|
136
|
+
},
|
|
137
|
+
],
|
|
126
138
|
});
|
|
127
139
|
});
|
|
128
140
|
});
|
|
@@ -156,6 +168,12 @@ function configureCycloneDXJSONLogger(logger, writer, config, hash) {
|
|
|
156
168
|
version: retire.version,
|
|
157
169
|
},
|
|
158
170
|
],
|
|
171
|
+
properties: repositories.length
|
|
172
|
+
? repositories.map((repo) => ({
|
|
173
|
+
name: 'retirejs:vulnerability-repository',
|
|
174
|
+
value: repo,
|
|
175
|
+
}))
|
|
176
|
+
: undefined,
|
|
159
177
|
},
|
|
160
178
|
components: components,
|
|
161
179
|
vulnerabilities: includeVEX ? Array.from(vulnerabilitiesCyclone.values()) : undefined,
|
|
@@ -65,6 +65,7 @@ function configureCycloneDXJSONLogger(logger, writer, config, hash) {
|
|
|
65
65
|
};
|
|
66
66
|
logger.close = function (callback) {
|
|
67
67
|
const write = vulnsFound ? writer.err : writer.out;
|
|
68
|
+
const repositories = (0, utils_1.vulnerabilityRepositories)(config.jsRepo);
|
|
68
69
|
const seen = new Map();
|
|
69
70
|
const components = finalResults.data
|
|
70
71
|
.filter((d) => d.results)
|
|
@@ -122,6 +123,12 @@ function configureCycloneDXJSONLogger(logger, writer, config, hash) {
|
|
|
122
123
|
version: retire.version,
|
|
123
124
|
},
|
|
124
125
|
],
|
|
126
|
+
properties: repositories.length
|
|
127
|
+
? repositories.map((repo) => ({
|
|
128
|
+
name: 'retirejs:vulnerability-repository',
|
|
129
|
+
value: repo,
|
|
130
|
+
}))
|
|
131
|
+
: undefined,
|
|
125
132
|
},
|
|
126
133
|
components: components,
|
|
127
134
|
}, undefined, 2));
|
|
@@ -65,6 +65,10 @@ function configureCycloneDXLogger(logger, writer, config, hash) {
|
|
|
65
65
|
};
|
|
66
66
|
logger.close = function (callback) {
|
|
67
67
|
const write = vulnsFound ? writer.err : writer.out;
|
|
68
|
+
const repositories = (0, utils_1.vulnerabilityRepositories)(config.jsRepo)
|
|
69
|
+
.map((repo) => `
|
|
70
|
+
<property name="retirejs:vulnerability-repository">${escapeXml(repo)}</property>`)
|
|
71
|
+
.join('');
|
|
68
72
|
const seen = new Set();
|
|
69
73
|
const components = finalResults.data
|
|
70
74
|
.filter((d) => d.results.length > 0)
|
|
@@ -109,7 +113,9 @@ function configureCycloneDXLogger(logger, writer, config, hash) {
|
|
|
109
113
|
<name>retire.js</name>
|
|
110
114
|
<version>${retire.version}</version>
|
|
111
115
|
</tool>
|
|
112
|
-
</tools
|
|
116
|
+
</tools>${repositories ? `
|
|
117
|
+
<properties>${repositories}
|
|
118
|
+
</properties>` : ''}
|
|
113
119
|
</metadata>
|
|
114
120
|
<components>${components}
|
|
115
121
|
</components>
|
|
@@ -117,6 +123,13 @@ function configureCycloneDXLogger(logger, writer, config, hash) {
|
|
|
117
123
|
writer.close(callback);
|
|
118
124
|
};
|
|
119
125
|
}
|
|
126
|
+
function escapeXml(value) {
|
|
127
|
+
return value
|
|
128
|
+
.replace(/&/g, '&')
|
|
129
|
+
.replace(/</g, '<')
|
|
130
|
+
.replace(/>/g, '>')
|
|
131
|
+
.replace(/"/g, '"');
|
|
132
|
+
}
|
|
120
133
|
function mapLicenses(licenses) {
|
|
121
134
|
if (!licenses)
|
|
122
135
|
return '';
|
package/lib/reporters/json.js
CHANGED
|
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
})();
|
|
36
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
37
|
const retire = __importStar(require("../retire"));
|
|
38
|
+
const utils_1 = require("./utils");
|
|
38
39
|
exports.default = {
|
|
39
40
|
configure: (logger, writer, config) => {
|
|
40
41
|
const scanStart = Date.now();
|
|
@@ -45,6 +46,7 @@ exports.default = {
|
|
|
45
46
|
messages: [],
|
|
46
47
|
errors: [],
|
|
47
48
|
time: undefined,
|
|
49
|
+
vulnerabilityRepositories: (0, utils_1.vulnerabilityRepositories)(config.jsRepo),
|
|
48
50
|
};
|
|
49
51
|
logger.info = finalResults.messages.push;
|
|
50
52
|
logger.debug = config.verbose
|
package/lib/reporters/utils.d.ts
CHANGED
|
@@ -1,2 +1,6 @@
|
|
|
1
1
|
import { Component } from '../types';
|
|
2
2
|
export declare function generatePURL(component: Component): string;
|
|
3
|
+
/**
|
|
4
|
+
* The vulnerability repositories used for the scan, as configured via --jsrepo.
|
|
5
|
+
*/
|
|
6
|
+
export declare function vulnerabilityRepositories(jsRepo: string[] | undefined): string[];
|
package/lib/reporters/utils.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.generatePURL = generatePURL;
|
|
4
|
+
exports.vulnerabilityRepositories = vulnerabilityRepositories;
|
|
4
5
|
function encodePURLchars(str) {
|
|
5
6
|
return str.replace(/[^A-Za-z0-9.+/=%-]/g, (match) => '%' + ('0' + match.charCodeAt(0).toString(16).toUpperCase()).slice(-2));
|
|
6
7
|
}
|
|
@@ -13,3 +14,11 @@ function generatePURL(component) {
|
|
|
13
14
|
const compName = component.npmname || component.component;
|
|
14
15
|
return `pkg:npm/${encodePURLchars(compName)}@${encodePURLchars(component.version)}`;
|
|
15
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* The vulnerability repositories used for the scan, as configured via --jsrepo.
|
|
19
|
+
*/
|
|
20
|
+
function vulnerabilityRepositories(jsRepo) {
|
|
21
|
+
if (!jsRepo)
|
|
22
|
+
return [];
|
|
23
|
+
return jsRepo.map((repo) => repo.trim()).filter((repo) => repo.length > 0);
|
|
24
|
+
}
|
package/lib/reporting.d.ts
CHANGED
package/lib/retire.js
CHANGED
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"author": "Erlend Oftedal <erlend@oftedal.no>",
|
|
3
3
|
"name": "retire",
|
|
4
4
|
"description": "Retire is a tool for detecting use of vulnerable libraries",
|
|
5
|
-
"version": "5.
|
|
5
|
+
"version": "5.5.0",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
@@ -14,30 +14,26 @@
|
|
|
14
14
|
"main": "./lib/retire.js",
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"ansi-colors": "^4.1.1",
|
|
17
|
-
"astronomical": "^3.
|
|
17
|
+
"astronomical": "^3.2.0",
|
|
18
18
|
"commander": "^10.0.1",
|
|
19
19
|
"proxy-agent": "^6.4.0",
|
|
20
20
|
"walkdir": "0.4.1",
|
|
21
21
|
"zod": "^3.22.4"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@types/chai": "^4.3.17",
|
|
25
|
-
"@types/jest": "^29.5.14",
|
|
26
24
|
"@types/node": "^18.13.0",
|
|
27
25
|
"@types/uuid": "^9.0.0",
|
|
28
26
|
"@typescript-eslint/eslint-plugin": "^7.1.1",
|
|
29
27
|
"@typescript-eslint/parser": "^7.1.1",
|
|
30
|
-
"chai": "^4.x.x",
|
|
31
28
|
"eslint": "^8.34.0",
|
|
32
29
|
"eslint-config-prettier": "^9.0.0",
|
|
33
30
|
"jsonschema": "^1.4.1",
|
|
34
31
|
"prettier": "^3.1.0",
|
|
35
|
-
"ts-jest": "^29.3.4",
|
|
36
32
|
"ts-node": "^10.9.2",
|
|
37
33
|
"typescript": "^5.0.4"
|
|
38
34
|
},
|
|
39
35
|
"scripts": {
|
|
40
|
-
"test": "
|
|
36
|
+
"test": "TS_NODE_PROJECT=tsconfig.spec.json node --require ts-node/register --test \"spec/tests/**/*.spec.ts\"",
|
|
41
37
|
"build": "tsc && chmod ugo+x lib/cli.js && cp src/retire.d.ts lib/retire.d.ts && cp ../LICENSE.md .",
|
|
42
38
|
"watch": "tsc --watch ",
|
|
43
39
|
"typecheck": "tsc --noEmit",
|