retire 5.0.0 → 5.1.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 CHANGED
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## [5.1.0]
4
+
5
+ ## Add
6
+
7
+ - Support for CycloneDX 1.6 JSON as output format
8
+ - Adding file location as property in CycloneDX 1.4 JSON output
9
+
10
+ ## [5.0.1]
11
+
12
+ ### Fix
13
+
14
+ - Fix filename issue for windows file paths
15
+
16
+ ## [5.0.0]
17
+
18
+ No changes. Just moving from beta to final.
19
+
3
20
  ## [5.0.0-beta.1]
4
21
 
5
22
  ### Added
package/lib/cli.js CHANGED
@@ -60,7 +60,7 @@ const prg = commander_1.program
60
60
  .option('--jsrepo <path|url>', "Local or internal version of repo. Can be multiple comma separated. Default: 'central')")
61
61
  .option('--cachedir <path>', 'Path to use for local cache instead of /tmp/.retire-cache')
62
62
  .option('--proxy <url>', 'Proxy url (http://some.host:8080)')
63
- .option('--outputformat <format>', 'Valid formats: text, json, jsonsimple, depcheck (experimental), cyclonedx and cyclonedxJSON')
63
+ .option('--outputformat <format>', 'Valid formats: text, json, jsonsimple, depcheck (experimental), cyclonedx, cyclonedxJSON and cyclonedxJSON1_6')
64
64
  .option('--outputpath <path>', 'File to which output should be written')
65
65
  .option('--ignore <paths>', 'Comma delimited list of paths to ignore')
66
66
  .option('--ignorefile <path>', 'Custom ignore file, defaults to .retireignore / .retireignore.json')
package/lib/deepscan.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.deepScan = void 0;
3
+ exports.deepScan = deepScan;
4
4
  const astronomical_1 = require("astronomical");
5
5
  function deepScan(content, repo) {
6
6
  const astQueries = {};
@@ -34,4 +34,3 @@ function deepScan(content, repo) {
34
34
  return acc;
35
35
  }, []);
36
36
  }
37
- exports.deepScan = deepScan;
package/lib/depsdev.js CHANGED
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.checkOSV = void 0;
6
+ exports.checkOSV = checkOSV;
7
7
  const https_1 = __importDefault(require("https"));
8
8
  const retire_1 = require("./retire");
9
9
  function loadJson(url, options) {
@@ -80,4 +80,3 @@ async function checkOSV(packageName, version, options) {
80
80
  return [];
81
81
  }
82
82
  }
83
- exports.checkOSV = checkOSV;
package/lib/repo.js CHANGED
@@ -23,7 +23,10 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.loadrepositoryFromFile = exports.loadrepository = exports.asbowerrepo = exports.validateRepository = void 0;
26
+ exports.validateRepository = validateRepository;
27
+ exports.asbowerrepo = asbowerrepo;
28
+ exports.loadrepository = loadrepository;
29
+ exports.loadrepositoryFromFile = loadrepositoryFromFile;
27
30
  const fs = __importStar(require("fs"));
28
31
  const path = __importStar(require("path"));
29
32
  const http = __importStar(require("http"));
@@ -151,7 +154,6 @@ function validateRepository(repo, replacer) {
151
154
  .strict());
152
155
  return validator.safeParse(repo);
153
156
  }
154
- exports.validateRepository = validateRepository;
155
157
  function formatValidationError(error) {
156
158
  return JSON.stringify(error.format(), (key, value) => (Array.isArray(value) && value.length === 0 ? undefined : value), 2);
157
159
  }
@@ -255,7 +257,6 @@ function asbowerrepo(jsRepo) {
255
257
  });
256
258
  return result;
257
259
  }
258
- exports.asbowerrepo = asbowerrepo;
259
260
  async function loadrepository(repoUrl, options) {
260
261
  options = { ...options, process: retire.replaceVersion };
261
262
  if (options.nocache) {
@@ -263,9 +264,7 @@ async function loadrepository(repoUrl, options) {
263
264
  }
264
265
  return await loadFromCache(repoUrl, options.cachedir, options);
265
266
  }
266
- exports.loadrepository = loadrepository;
267
267
  async function loadrepositoryFromFile(filepath, options) {
268
268
  options = { ...options, process: retire.replaceVersion };
269
269
  return await loadJsonFromFile(filepath, options);
270
270
  }
271
- exports.loadrepositoryFromFile = loadrepositoryFromFile;
@@ -0,0 +1,3 @@
1
+ import { ConfigurableLogger } from '../reporting';
2
+ declare const _default: ConfigurableLogger;
3
+ export default _default;
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ const retire = __importStar(require("../retire"));
27
+ const fs = __importStar(require("fs"));
28
+ const uuid_1 = require("uuid");
29
+ const utils_1 = require("./utils");
30
+ const path = __importStar(require("path"));
31
+ function configureCycloneDXJSONLogger(logger, writer, config, hash) {
32
+ let vulnsFound = false;
33
+ const finalResults = {
34
+ version: retire.version,
35
+ start: new Date().toISOString(),
36
+ data: [],
37
+ messages: [],
38
+ errors: [],
39
+ };
40
+ logger.info = finalResults.messages.push;
41
+ logger.debug = config.verbose
42
+ ? finalResults.messages.push
43
+ : function () {
44
+ return;
45
+ };
46
+ logger.warn = logger.error = finalResults.errors.push;
47
+ logger.logVulnerableDependency = function (finding) {
48
+ vulnsFound = true;
49
+ finalResults.data.push(finding);
50
+ };
51
+ logger.logDependency = function (finding) {
52
+ if (finding.results.length > 0) {
53
+ finalResults.data.push(finding);
54
+ }
55
+ };
56
+ logger.close = function (callback) {
57
+ const write = vulnsFound ? writer.err : writer.out;
58
+ const seen = new Map();
59
+ const components = finalResults.data
60
+ .filter((d) => d.results)
61
+ .map((r) => r.results
62
+ .map((dep) => {
63
+ dep.version = (dep.version.split('.').length >= 3 ? dep.version : dep.version + '.0').replace(/-/g, '.');
64
+ let hashes;
65
+ const filepath = r.file;
66
+ const evidence = { occurrences: [] };
67
+ if (filepath) {
68
+ const file = fs.readFileSync(filepath);
69
+ const relativePath = path.relative(process.cwd(), filepath);
70
+ evidence.occurrences.push({ location: relativePath });
71
+ hashes = [
72
+ { alg: 'MD5', content: hash.md5(file) },
73
+ { alg: 'SHA-1', content: hash.sha1(file) },
74
+ { alg: 'SHA-256', content: hash.sha256(file) },
75
+ { alg: 'SHA-512', content: hash.sha512(file) },
76
+ ];
77
+ }
78
+ const purl = (0, utils_1.generatePURL)(dep);
79
+ if (seen.has(purl)) {
80
+ seen.get(purl)?.evidence.occurrences.push(...evidence.occurrences);
81
+ return undefined;
82
+ }
83
+ const result = {
84
+ type: 'library',
85
+ name: dep.component,
86
+ version: dep.version,
87
+ purl: purl,
88
+ hashes: hashes,
89
+ evidence,
90
+ };
91
+ seen.set(purl, result);
92
+ return result;
93
+ })
94
+ .filter((x) => x != undefined))
95
+ .reduce((a, b) => a.concat(b), []);
96
+ write(JSON.stringify({
97
+ bomFormat: 'CycloneDX',
98
+ specVersion: '1.6',
99
+ serialNumber: `urn:uuid:${(0, uuid_1.v4)()}`,
100
+ version: 1,
101
+ metadata: {
102
+ timestamp: finalResults.start,
103
+ tools: [
104
+ {
105
+ vendor: 'RetireJS',
106
+ name: 'retire.js',
107
+ version: retire.version,
108
+ },
109
+ ],
110
+ },
111
+ components: components,
112
+ }, undefined, 2));
113
+ writer.close(callback);
114
+ };
115
+ }
116
+ exports.default = {
117
+ configure: configureCycloneDXJSONLogger,
118
+ };
@@ -1,5 +1,4 @@
1
1
  "use strict";
2
- /*jshint esversion: 6 */
3
2
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
3
  if (k2 === undefined) k2 = k;
5
4
  var desc = Object.getOwnPropertyDescriptor(m, k);
@@ -28,6 +27,7 @@ const retire = __importStar(require("../retire"));
28
27
  const fs = __importStar(require("fs"));
29
28
  const uuid_1 = require("uuid");
30
29
  const utils_1 = require("./utils");
30
+ const path = __importStar(require("path"));
31
31
  function configureCycloneDXJSONLogger(logger, writer, config, hash) {
32
32
  let vulnsFound = false;
33
33
  const finalResults = {
@@ -63,8 +63,11 @@ function configureCycloneDXJSONLogger(logger, writer, config, hash) {
63
63
  dep.version = (dep.version.split('.').length >= 3 ? dep.version : dep.version + '.0').replace(/-/g, '.');
64
64
  let hashes;
65
65
  const filepath = r.file;
66
+ const properties = [];
66
67
  if (filepath) {
67
68
  const file = fs.readFileSync(filepath);
69
+ const relativePath = path.relative(process.cwd(), filepath);
70
+ properties.push({ name: 'location', value: relativePath });
68
71
  hashes = [
69
72
  { alg: 'MD5', content: hash.md5(file) },
70
73
  { alg: 'SHA-1', content: hash.sha1(file) },
@@ -82,6 +85,7 @@ function configureCycloneDXJSONLogger(logger, writer, config, hash) {
82
85
  version: dep.version,
83
86
  purl: purl,
84
87
  hashes: hashes,
88
+ properties,
85
89
  };
86
90
  })
87
91
  .filter((x) => x != undefined))
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.generatePURL = void 0;
3
+ exports.generatePURL = generatePURL;
4
4
  function generatePURL(component) {
5
5
  if (component.basePurl) {
6
6
  return component.basePurl + '@' + component.version;
@@ -8,4 +8,3 @@ function generatePURL(component) {
8
8
  const compName = component.npmname || component.component;
9
9
  return `pkg:npm/${compName}@${component.version}`;
10
10
  }
11
- exports.generatePURL = generatePURL;
@@ -1,6 +1,3 @@
1
- /// <reference types="node" />
2
- /// <reference types="node" />
3
- /// <reference types="node" />
4
1
  import { Finding } from './types';
5
2
  export type LoggerOptions = {
6
3
  outputpath: string;
package/lib/reporting.js CHANGED
@@ -26,7 +26,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
26
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.open = exports.hash = void 0;
29
+ exports.hash = void 0;
30
+ exports.open = open;
30
31
  const fs = __importStar(require("fs"));
31
32
  const crypto = __importStar(require("crypto"));
32
33
  const console_1 = __importDefault(require("./reporters/console"));
@@ -34,6 +35,7 @@ const json_1 = __importDefault(require("./reporters/json"));
34
35
  const depcheck_1 = __importDefault(require("./reporters/depcheck"));
35
36
  const cyclonedx_1 = __importDefault(require("./reporters/cyclonedx"));
36
37
  const cyclonedx_json_1 = __importDefault(require("./reporters/cyclonedx-json"));
38
+ const cyclonedx_1_6_json_1 = __importDefault(require("./reporters/cyclonedx-1_6-json"));
37
39
  const loggers = {
38
40
  console: console_1.default,
39
41
  text: console_1.default,
@@ -41,6 +43,7 @@ const loggers = {
41
43
  depcheck: depcheck_1.default,
42
44
  cyclonedx: cyclonedx_1.default,
43
45
  cyclonedxJSON: cyclonedx_json_1.default,
46
+ cyclonedxJSON1_6: cyclonedx_1_6_json_1.default,
44
47
  clean: console_1.default,
45
48
  jsonsimple: json_1.default,
46
49
  };
@@ -127,4 +130,3 @@ function open(config) {
127
130
  configureFileWriter(config);
128
131
  return logger;
129
132
  }
130
- exports.open = open;
package/lib/resolve.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- /// <reference types="node" />
2
1
  import { EventEmitter as Emitter } from 'events';
3
2
  import { Options } from './types';
4
3
  export declare function scanJsFiles(path: string, options: Options): Emitter;
package/lib/resolve.js CHANGED
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.scanJsFiles = void 0;
26
+ exports.scanJsFiles = scanJsFiles;
27
27
  const fs = __importStar(require("fs"));
28
28
  const walkdir = __importStar(require("walkdir"));
29
29
  function scanJsFiles(path, options) {
@@ -51,4 +51,3 @@ function scanJsFiles(path, options) {
51
51
  });
52
52
  return finder;
53
53
  }
54
- exports.scanJsFiles = scanJsFiles;
package/lib/retire.js CHANGED
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  var exports = exports || {};
7
- exports.version = '5.0.0';
7
+ exports.version = '5.1.0';
8
8
 
9
9
  function isDefined(o) {
10
10
  return typeof o !== 'undefined';
@@ -168,7 +168,7 @@ exports.scanUri = function (uri, repo) {
168
168
  };
169
169
 
170
170
  exports.scanFileName = function (fileName, repo) {
171
- var result = scan(fileName, 'filename', repo, splitAndMatchAll('/'));
171
+ var result = scan(fileName, 'filename', repo, splitAndMatchAll(/[\/\\]/));
172
172
  return check(result, repo);
173
173
  };
174
174
 
package/lib/scanner.js CHANGED
@@ -23,7 +23,9 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.on = exports.scanBowerFile = exports.scanJsFile = void 0;
26
+ exports.scanJsFile = scanJsFile;
27
+ exports.scanBowerFile = scanBowerFile;
28
+ exports.on = on;
27
29
  const events_1 = require("events");
28
30
  const retire = __importStar(require("./retire"));
29
31
  const fs = __importStar(require("fs"));
@@ -137,7 +139,6 @@ function scanJsFile(file, repo, options) {
137
139
  }
138
140
  emitResults({ file: file, results: results }, options);
139
141
  }
140
- exports.scanJsFile = scanJsFile;
141
142
  function scanBowerFile(file, repo, options) {
142
143
  if (options.ignore && shouldIgnorePath([file], options.ignore)) {
143
144
  return;
@@ -153,8 +154,6 @@ function scanBowerFile(file, repo, options) {
153
154
  options.log.warn(`Could not parse file: ${file}`);
154
155
  }
155
156
  }
156
- exports.scanBowerFile = scanBowerFile;
157
157
  function on(event, handler) {
158
158
  events.on(event, handler);
159
159
  }
160
- exports.on = on;
package/lib/types.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- /// <reference types="node" />
2
1
  import { Logger } from './reporting';
3
2
  export type Repository = Record<string, {
4
3
  bowername?: string[];
package/lib/utils.js CHANGED
@@ -1,18 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.flatten = exports.pick = exports.warn = exports.info = void 0;
3
+ exports.info = info;
4
+ exports.warn = warn;
5
+ exports.pick = pick;
6
+ exports.flatten = flatten;
4
7
  function info(options) {
5
8
  return function (...message) {
6
9
  (options.logger || console.log)(message);
7
10
  };
8
11
  }
9
- exports.info = info;
10
12
  function warn(options) {
11
13
  return function (...message) {
12
14
  (options.warnlogger || options.logger || console.warn)(message);
13
15
  };
14
16
  }
15
- exports.warn = warn;
16
17
  function pick(p, keys) {
17
18
  const result = {};
18
19
  keys.forEach((k) => {
@@ -22,8 +23,6 @@ function pick(p, keys) {
22
23
  });
23
24
  return result;
24
25
  }
25
- exports.pick = pick;
26
26
  function flatten(e) {
27
27
  return e.reduce((x, y) => x.concat(y), []);
28
28
  }
29
- exports.flatten = flatten;
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.0.0",
5
+ "version": "5.1.0",
6
6
  "license": "Apache-2.0",
7
7
  "repository": {
8
8
  "type": "git",
@@ -30,10 +30,10 @@
30
30
  "eslint": "^8.34.0",
31
31
  "eslint-config-prettier": "^9.0.0",
32
32
  "jsonschema": "^1.4.1",
33
- "libxmljs": "^1.0.8",
34
33
  "mocha": "^10.2.0",
35
34
  "prettier": "^3.1.0",
36
- "typescript": "^5.0.4"
35
+ "typescript": "^5.0.4",
36
+ "xsd-schema-validator": "^0.9.0"
37
37
  },
38
38
  "scripts": {
39
39
  "test": "./test",