@contrast/contrast 1.0.22 → 2.0.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.
Files changed (77) hide show
  1. package/README.md +21 -138
  2. package/dist/audit/languageAnalysisEngine/sendSnapshot.js +2 -19
  3. package/dist/audit/report/commonReportingFunctions.js +1 -1
  4. package/dist/audit/save.js +16 -5
  5. package/dist/cliConstants.js +29 -0
  6. package/dist/commands/audit/auditController.js +2 -1
  7. package/dist/commands/audit/help.js +3 -3
  8. package/dist/commands/audit/processAudit.js +3 -1
  9. package/dist/commands/audit/saveFile.js +5 -1
  10. package/dist/commands/github/projectGroup.js +164 -0
  11. package/dist/common/HTTPClient.js +165 -13
  12. package/dist/constants/constants.js +3 -5
  13. package/dist/constants/locales.js +7 -3
  14. package/dist/index.js +0 -4
  15. package/dist/lambda/lambda.js +3 -1
  16. package/dist/sbom/generateSbom.js +7 -0
  17. package/dist/scaAnalysis/common/commonReportingFunctionsSca.js +6 -6
  18. package/dist/scaAnalysis/common/scaServicesUpload.js +77 -7
  19. package/dist/scaAnalysis/common/treeUpload.js +1 -1
  20. package/dist/scaAnalysis/go/goAnalysis.js +1 -1
  21. package/dist/scaAnalysis/java/analysis.js +24 -32
  22. package/dist/scaAnalysis/java/index.js +1 -1
  23. package/dist/scaAnalysis/javascript/index.js +3 -3
  24. package/dist/scaAnalysis/legacy/legacyFlow.js +33 -0
  25. package/dist/scaAnalysis/php/index.js +1 -1
  26. package/dist/scaAnalysis/processServicesFlow.js +21 -0
  27. package/dist/scaAnalysis/python/analysis.js +1 -1
  28. package/dist/scaAnalysis/python/index.js +1 -1
  29. package/dist/scaAnalysis/repoMode/index.js +2 -2
  30. package/dist/scaAnalysis/ruby/analysis.js +1 -1
  31. package/dist/scaAnalysis/ruby/index.js +1 -1
  32. package/dist/scaAnalysis/scaAnalysis.js +16 -36
  33. package/dist/scan/autoDetection.js +41 -2
  34. package/dist/scan/fileUtils.js +5 -4
  35. package/dist/utils/commonApi.js +26 -1
  36. package/dist/utils/settingsHelper.js +7 -17
  37. package/package.json +6 -6
  38. package/src/audit/languageAnalysisEngine/sendSnapshot.js +3 -22
  39. package/src/audit/report/commonReportingFunctions.js +1 -1
  40. package/src/audit/save.js +21 -10
  41. package/src/cliConstants.js +32 -0
  42. package/src/commands/audit/auditController.js +2 -1
  43. package/src/commands/audit/help.js +3 -3
  44. package/src/commands/audit/processAudit.js +4 -5
  45. package/src/commands/audit/saveFile.js +6 -1
  46. package/src/commands/github/projectGroup.js +187 -0
  47. package/src/common/HTTPClient.js +221 -13
  48. package/src/constants/constants.js +3 -5
  49. package/src/constants/locales.js +9 -3
  50. package/src/index.ts +0 -5
  51. package/src/lambda/lambda.ts +3 -1
  52. package/src/lambda/lambdaUtils.ts +1 -1
  53. package/src/sbom/generateSbom.ts +8 -0
  54. package/src/scaAnalysis/common/commonReportingFunctionsSca.js +6 -6
  55. package/src/scaAnalysis/common/scaServicesUpload.js +92 -7
  56. package/src/scaAnalysis/common/treeUpload.js +1 -1
  57. package/src/scaAnalysis/go/goAnalysis.js +1 -1
  58. package/src/scaAnalysis/java/analysis.js +29 -34
  59. package/src/scaAnalysis/java/index.js +1 -1
  60. package/src/scaAnalysis/javascript/index.js +3 -6
  61. package/src/scaAnalysis/legacy/legacyFlow.js +48 -0
  62. package/src/scaAnalysis/php/index.js +1 -1
  63. package/src/scaAnalysis/processServicesFlow.js +29 -0
  64. package/src/scaAnalysis/python/analysis.js +1 -1
  65. package/src/scaAnalysis/python/index.js +1 -1
  66. package/src/scaAnalysis/repoMode/index.js +2 -2
  67. package/src/scaAnalysis/ruby/analysis.js +1 -1
  68. package/src/scaAnalysis/ruby/index.js +1 -1
  69. package/src/scaAnalysis/scaAnalysis.js +21 -57
  70. package/src/scan/autoDetection.js +44 -3
  71. package/src/scan/fileUtils.js +5 -4
  72. package/src/utils/commonApi.js +29 -1
  73. package/src/utils/settingsHelper.js +8 -18
  74. package/dist/commands/fingerprint/processFingerprint.js +0 -14
  75. package/src/commands/fingerprint/processFingerprint.js +0 -21
  76. /package/dist/commands/{fingerprint → github}/fingerprintConfig.js +0 -0
  77. /package/src/commands/{fingerprint → github}/fingerprintConfig.js +0 -0
@@ -171,6 +171,18 @@ HTTPClient.prototype.scaServiceIngest = function scaServiceIngest(requestBody, c
171
171
  let url = createScaServiceIngestURL(config);
172
172
  options.url = url;
173
173
  options.body = requestBody;
174
+ if (config.debug || config.verbose) {
175
+ console.log('scaServiceIngest');
176
+ console.log('url', options.url);
177
+ console.log('body', options.body);
178
+ }
179
+ return requestUtils.sendRequest({ method: 'post', options });
180
+ };
181
+ HTTPClient.prototype.noProjectIdUpload = function scaServiceIngest(requestBody, config) {
182
+ const options = _.cloneDeep(this.requestOptions);
183
+ let url = createScaServiceNoProjectIdURL(config);
184
+ options.url = url;
185
+ options.body = requestBody;
174
186
  return requestUtils.sendRequest({ method: 'post', options });
175
187
  };
176
188
  HTTPClient.prototype.scaServiceReport = function scaServiceReport(config, reportId) {
@@ -179,18 +191,31 @@ HTTPClient.prototype.scaServiceReport = function scaServiceReport(config, report
179
191
  options.url = url;
180
192
  return requestUtils.sendRequest({ method: 'get', options });
181
193
  };
182
- HTTPClient.prototype.scaServiceReportStatus = function scaServiceReport(config, reportId) {
194
+ HTTPClient.prototype.scaServiceReportNoProjectId = function scaServiceReport(config, reportId) {
183
195
  const options = _.cloneDeep(this.requestOptions);
184
- let url = createScaServiceReportStatusURL(config, reportId);
185
- options.url = url;
196
+ options.url = createScaServiceReportNoProjectIdURL(config, reportId);
197
+ if (config.debug || config.verbose) {
198
+ console.log('createScaServiceReportNoProjectIdURL', options.url);
199
+ }
186
200
  return requestUtils.sendRequest({ method: 'get', options });
187
201
  };
188
- HTTPClient.prototype.scaServiceIngests = function scaServiceIngests(config) {
202
+ HTTPClient.prototype.scaServiceReportStatus = function scaServiceReport(config, reportId) {
189
203
  const options = _.cloneDeep(this.requestOptions);
190
- let url = createScaServiceIngestsURL(config);
191
- options.url = url;
204
+ options.url = createScaServiceReportStatusURL(config, reportId);
205
+ if (config.debug || config.verbose) {
206
+ console.log('createScaServiceReportStatusURL', options.url);
207
+ }
192
208
  return requestUtils.sendRequest({ method: 'get', options });
193
209
  };
210
+ HTTPClient.prototype.scaServiceNoProjectIdReportStatus =
211
+ function scaServiceReport(config, reportId) {
212
+ const options = _.cloneDeep(this.requestOptions);
213
+ options.url = createScaServiceReportStatusURL(config, reportId);
214
+ if (config.debug || config.verbose) {
215
+ console.log('createScaServiceReportStatusURL', options.url);
216
+ }
217
+ return requestUtils.sendRequest({ method: 'get', options });
218
+ };
194
219
  HTTPClient.prototype.scaServiceHealth = function scaServiceIngests(config) {
195
220
  const options = _.cloneDeep(this.requestOptions);
196
221
  let url = createScaServiceHealthURL(config);
@@ -225,6 +250,80 @@ HTTPClient.prototype.getAppId = function getAppId(config) {
225
250
  options.url = url;
226
251
  return requestUtils.sendRequest({ method: 'get', options });
227
252
  };
253
+ HTTPClient.prototype.registerRepo = function registerRepo(config, requestBody) {
254
+ const options = _.cloneDeep(this.requestOptions);
255
+ let url = createRepositoryUrl(config);
256
+ options.url = url;
257
+ options.body = requestBody;
258
+ return requestUtils.sendRequest({ method: 'post', options });
259
+ };
260
+ HTTPClient.prototype.registerProjectGroup = function (config, requestBody) {
261
+ const options = _.cloneDeep(this.requestOptions);
262
+ let url = registerProjectGroupUrl(config);
263
+ options.url = url;
264
+ options.body = requestBody;
265
+ if (config.debug || config.verbose) {
266
+ console.log('registerProjectGroup');
267
+ console.log('url', options.url);
268
+ console.log('body', options.body);
269
+ }
270
+ return requestUtils.sendRequest({ method: 'post', options });
271
+ };
272
+ HTTPClient.prototype.registerProject = function (config, projectGroupId) {
273
+ const options = _.cloneDeep(this.requestOptions);
274
+ let url = registerProjectUrl(config, projectGroupId);
275
+ options.url = url;
276
+ return requestUtils.sendRequest({ method: 'get', options });
277
+ };
278
+ HTTPClient.prototype.retrieveSourcesViaRepositoryId = function (config, repositoryId) {
279
+ const options = _.cloneDeep(this.requestOptions);
280
+ let url = retrieveSourcesUrl(config, repositoryId);
281
+ options.url = url;
282
+ return requestUtils.sendRequest({ method: 'get', options });
283
+ };
284
+ HTTPClient.prototype.retrieveRepoByOrgAndGitURL = function (config) {
285
+ const options = _.cloneDeep(this.requestOptions);
286
+ let url = retrieveRepoByOrgAndGitURL(config);
287
+ options.url = url;
288
+ return requestUtils.sendRequest({ method: 'get', options });
289
+ };
290
+ HTTPClient.prototype.registerOnCliServices = function (config, project) {
291
+ const options = _.cloneDeep(this.requestOptions);
292
+ let url = retrieveRegisterOnCliServicesUrl(config);
293
+ options.url = url;
294
+ options.body = project;
295
+ if (config.debug || config.verbose) {
296
+ console.log('registerOnCliServices');
297
+ console.log('url', options.url);
298
+ console.log('body', options.body);
299
+ }
300
+ return requestUtils.sendRequest({ method: 'post', options });
301
+ };
302
+ HTTPClient.prototype.retrieveProjectByOrganizationId = function registerRepo(config) {
303
+ const options = _.cloneDeep(this.requestOptions);
304
+ let url = retrieveProjectByOrganizationIdUrl(config);
305
+ options.url = url;
306
+ return requestUtils.sendRequest({ method: 'get', options });
307
+ };
308
+ HTTPClient.prototype.retrieveExistingProjectGroupsByOrg = function registerRepo(config) {
309
+ const options = _.cloneDeep(this.requestOptions);
310
+ let url = retrieveExistingGroupProjectsByOrgUrl(config);
311
+ options.url = url;
312
+ return requestUtils.sendRequest({ method: 'get', options });
313
+ };
314
+ HTTPClient.prototype.retrieveExistingProjectIdByProjectGroupId =
315
+ function registerRepo(config, projectGroupId) {
316
+ const options = _.cloneDeep(this.requestOptions);
317
+ let url = retrieveExistingGroupProjectsByGroupIdUrl(config, projectGroupId);
318
+ options.url = url;
319
+ return requestUtils.sendRequest({ method: 'get', options });
320
+ };
321
+ HTTPClient.prototype.retrieveExistingRepo = function registerRepo(config) {
322
+ const options = _.cloneDeep(this.requestOptions);
323
+ let url = retrieveExistingRepoUrl(config);
324
+ options.url = url;
325
+ return requestUtils.sendRequest({ method: 'get', options });
326
+ };
228
327
  function getServerlessHost(config = {}) {
229
328
  const originalHost = config?.host || config?.get('host');
230
329
  const host = originalHost?.endsWith('/')
@@ -338,22 +437,37 @@ function createSnapshotURL(config) {
338
437
  return `${config.host}/Contrast/api/ng/sca/organizations/${config.organizationId}/applications/${config.applicationId}/snapshots`;
339
438
  }
340
439
  function createScaServiceReportURL(config, reportId) {
341
- let baseUrl = `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/applications/${config.applicationId}/libraries/reports/${reportId}`;
440
+ let baseUrl = `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/projects/${config.projectId}/libraries/reports/${reportId}`;
441
+ baseUrl = config.ignoreDev ? baseUrl.concat('?nodesToInclude=PROD') : baseUrl;
442
+ return baseUrl;
443
+ }
444
+ function createScaServiceReportNoProjectIdURL(config, reportId) {
445
+ let baseUrl = `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/libraries/reports/${reportId}`;
342
446
  baseUrl = config.ignoreDev ? baseUrl.concat('?nodesToInclude=PROD') : baseUrl;
343
447
  return baseUrl;
344
448
  }
345
449
  function createScaServiceReportStatusURL(config, reportId) {
346
- return `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/applications/${config.applicationId}/libraries/ingests/${reportId}/status`;
450
+ return `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/libraries/ingests/${reportId}/status`;
347
451
  }
348
- function createScaServiceIngestsURL(config) {
349
- return `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/applications/${config.applicationId}/libraries/ingests`;
452
+ function createScaServiceNoProjectIdURL(config) {
453
+ return `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/libraries/ingests/tree${config.repo ? '?incomplete=true' : ''}`;
350
454
  }
351
455
  function createScaServiceHealthURL(config) {
352
456
  return `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/health`;
353
457
  }
354
458
  function createScaServiceIngestURL(config) {
355
- let baseUrl = `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/applications/${config.applicationId}/libraries/ingests/tree`;
356
- baseUrl = config.track ? baseUrl.concat('?persist=true') : baseUrl;
459
+ let optionalParams = [];
460
+ config.repo ? optionalParams.push('incomplete=true') : null;
461
+ config.track ? optionalParams.push('persist=true') : null;
462
+ let params = '?';
463
+ optionalParams.forEach(param => {
464
+ params = params.concat(param);
465
+ params = params.concat('&');
466
+ });
467
+ let baseUrl = `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/projects/${config.projectId}/libraries/ingests/tree${params}`;
468
+ if (config.debug) {
469
+ console.log('createScaServiceIngestURL', baseUrl);
470
+ }
357
471
  return baseUrl;
358
472
  }
359
473
  const createAppCreateURL = config => {
@@ -362,6 +476,42 @@ const createAppCreateURL = config => {
362
476
  const createAppNameUrl = config => {
363
477
  return `${config.host}/Contrast/api/ng/${config.organizationId}/applications/name?filterText=${config.applicationName}`;
364
478
  };
479
+ const registerProjectGroupUrl = config => {
480
+ return `${config.host}/api/v4/organizations/${config.organizationId}/project-groups`;
481
+ };
482
+ const registerProjectUrl = (config, projectGroupId) => {
483
+ return `${config.host}/api/v4/organizations/${config.organizationId}/project-groups/${projectGroupId}/projects`;
484
+ };
485
+ const retrieveRegisterOnCliServicesUrl = config => {
486
+ return `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/projects`;
487
+ };
488
+ const retrieveSourcesUrl = (config, repositoryId) => {
489
+ return `${config.host}/projects/v1/repositories/${repositoryId}/sources`;
490
+ };
491
+ const retrieveRepoByOrgAndGitURL = config => {
492
+ return `${config.host}/api/v4/organizations/${config.organizationId}/repository`;
493
+ };
494
+ const retrieveProjectByOrganizationIdUrl = config => {
495
+ let baseUrl = `${config.host}/api/v4/organizations/${config.organizationId}/projects`;
496
+ baseUrl = config.name ? baseUrl.concat(`?name=${config.name}`) : baseUrl;
497
+ baseUrl = config.language
498
+ ? baseUrl.concat(`&language=${config.language}`)
499
+ : baseUrl;
500
+ baseUrl = config.language ? baseUrl.concat(`&source=SCA`) : baseUrl;
501
+ return baseUrl;
502
+ };
503
+ const retrieveExistingGroupProjectsByOrgUrl = config => {
504
+ return `${config.host}/api/v4/organizations/${config.organizationId}/project-groups`;
505
+ };
506
+ const retrieveExistingGroupProjectsByGroupIdUrl = (config, projectGroupId) => {
507
+ return `${config.host}/api/v4/organizations/${config.organizationId}/projects/${projectGroupId}/projects`;
508
+ };
509
+ const retrieveExistingRepoUrl = config => {
510
+ return `${config.host}/projects/v4/organizations/${config.organizationId}/repositories`;
511
+ };
512
+ function createRepositoryUrl(config) {
513
+ return `${config.host}/projects/v1/repositories`;
514
+ }
365
515
  function createLibraryVulnerabilitiesUrl(config) {
366
516
  return `${config.host}/Contrast/api/ng/${config.organizationId}/libraries/artifactsByGroupNameVersion`;
367
517
  }
@@ -381,7 +531,9 @@ function createSbomUrl(config, type) {
381
531
  return `${config.host}/Contrast/api/ng/${config.organizationId}/applications/${config.applicationId}/libraries/sbom/${type}`;
382
532
  }
383
533
  function createSCASbomUrl(config, type, reportId) {
384
- return `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/libraries/applications/${config.applicationId}/sbom/${reportId}?toolType=${type}`;
534
+ return config.projectId
535
+ ? `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/projects/${config.projectId}/libraries/sbom/${reportId}?toolType=${type}`
536
+ : `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/libraries/sbom/${reportId}?toolType=${type}`;
385
537
  }
386
538
  function createTelemetryEventUrl(config) {
387
539
  return `${config.host}/Contrast/api/sast/organizations/${config.organizationId}/cli`;
@@ -12,7 +12,7 @@ const MEDIUM = 'MEDIUM';
12
12
  const HIGH = 'HIGH';
13
13
  const CRITICAL = 'CRITICAL';
14
14
  const APP_NAME = 'contrast';
15
- const APP_VERSION = '1.0.22';
15
+ const APP_VERSION = '2.0.0';
16
16
  const TIMEOUT = 120000;
17
17
  const HIGH_COLOUR = '#ff9900';
18
18
  const CRITICAL_COLOUR = '#e35858';
@@ -27,12 +27,11 @@ const NOTE_PRIORITY = 5;
27
27
  const AUTH_UI_URL = 'https://cli-auth.contrastsecurity.com';
28
28
  const AUTH_CALLBACK_URL = 'https://cli-auth-api.contrastsecurity.com';
29
29
  const SARIF_FILE = 'SARIF';
30
- const SBOM_CYCLONE_DX_FILE = 'cyclonedx';
31
- const SBOM_SPDX_FILE = 'spdx';
30
+ const SBOM_CYCLONE_DX_FILE = 'CYCLONEDX';
31
+ const SBOM_SPDX_FILE = 'SPDX';
32
32
  const CE_URL = 'https://ce.contrastsecurity.com';
33
33
  const SAAS = 'SAAS';
34
34
  const EOP = 'EOP';
35
- const MODE_BUILD = 'BUILD';
36
35
  const MODE_REPO = 'REPO';
37
36
  module.exports = {
38
37
  supportedLanguages: { NODE, DOTNET, JAVA, RUBY, PYTHON, GO, PHP, JAVASCRIPT },
@@ -62,6 +61,5 @@ module.exports = {
62
61
  SBOM_SPDX_FILE,
63
62
  SAAS,
64
63
  EOP,
65
- MODE_BUILD,
66
64
  MODE_REPO
67
65
  };
@@ -48,7 +48,7 @@ const en_locales = () => {
48
48
  constantsProxyServer: 'Allows for connection via a proxy server. If authentication is required please provide the username and password with the protocol, host and port. For instance: "https://username:password@<host>:<port>".',
49
49
  constantsGradleMultiProject: 'Specify the sub project within your gradle application.',
50
50
  constantsDoNotWaitForScan: 'Fire and forget. Do not wait for the result of the scan.',
51
- constantsProjectName: 'Contrast project name. If not specified, Contrast uses contrast.settings to identify the project or creates a project.',
51
+ constantsProjectName: 'Contrast project name. If not specified, Contrast uses the file / folder name to identify the project or creates a new project.',
52
52
  constantsProjectId: 'The ID associated with a scan project. Replace <ProjectID> with the ID for the scan project. To find the ID, select a scan project in Contrast and locate the last number in the URL.',
53
53
  failThresholdOptionErrorMessage: 'More than 0 vulnerabilities found',
54
54
  failSeverityOptionErrorMessage: ' FAIL - Results detected vulnerabilities over accepted severity level',
@@ -130,8 +130,12 @@ const en_locales = () => {
130
130
  scanOptionsTimeoutSummary: 'Time in seconds to wait for scan to complete. Default value is 300 seconds.',
131
131
  scanOptionsFileNameSummary: 'Path of the file you want to scan. If no file is specified, Contrast searches for a .jar, .war, .exe or .zip file in the working directory.',
132
132
  scanOptionsVerboseSummary: ' Returns extended information to the terminal.',
133
- auditOptionsTrackSummary: ' Save the results to the UI.',
133
+ auditOptionsTrackSummary: ' Send your dependency audit to Contrast to see results in the UI and start automating security checks. For instance when running local SCA checks you may not need or want to track the results.',
134
134
  auditOptionsBranchSummary: ' Set the branch name to associate the library results to.',
135
+ auditOptionsLegacySummary: ' Creates an application in Contrast (a legacy workflow) - displays a dependency tree for your piece of code, utilizes metatdata.' +
136
+ '\n' +
137
+ '.NET is only supported using --legacy\n',
138
+ auditOptionsRepoSummary: ' Run in repo mode.',
135
139
  authSuccessMessage: 'Authentication successful',
136
140
  runAuthSuccessMessage: chalk.bold('CodeSec by Contrast') +
137
141
  '\nScan, secure and ship your code in minutes for FREE. \n' +
@@ -193,7 +197,7 @@ const en_locales = () => {
193
197
  If you are running on untrusted code, consider running in a sandbox.`,
194
198
  constantsAuditPrerequisitesContentDotNetMessage: `
195
199
  ${chalk.bold('.NET framework and .NET core:')} MSBuild 15.0 or greater and a packages.lock.json file.
196
- Note: If the packages.lock.json file is unavailable it can be generated by setting RestorePackagesWithLockFile to true within each *.csproj file and running dotnet build.\n`,
200
+ Note: If the packages.lock.json file is unavailable it can be generated by setting RestorePackagesWithLockFile to true within each *.csproj file and running dotnet build. Only supported with the --legacy flag, an older workflow\n`,
197
201
  constantsAuditPrerequisitesContentNodeMessage: `${chalk.bold('Node:')} package.json and a lock file (either .package-lock.json or .yarn.lock.)\n`,
198
202
  constantsAuditPrerequisitesContentRubyMessage: `${chalk.bold('Ruby:')} gemfile and gemfile.lock\n`,
199
203
  constantsAuditPrerequisitesContentPythonMessage: `${chalk.bold('Python:')} pipfile and pipfile.lock\n`,
package/dist/index.js CHANGED
@@ -9,7 +9,6 @@ const processAudit_1 = require("./commands/audit/processAudit");
9
9
  const auth_1 = require("./commands/auth/auth");
10
10
  const config_1 = require("./commands/config/config");
11
11
  const processScan_1 = require("./commands/scan/processScan");
12
- const processFingerprint_1 = require("./commands/fingerprint/processFingerprint");
13
12
  const cliConstants_1 = __importDefault(require("./cliConstants"));
14
13
  const constants_1 = require("./constants/constants");
15
14
  const lambda_1 = require("./lambda/lambda");
@@ -69,9 +68,6 @@ const start = async () => {
69
68
  if (command === 'learn') {
70
69
  return (0, processLearn_1.processLearn)();
71
70
  }
72
- if (command === 'fingerprint') {
73
- return await (0, processFingerprint_1.processFingerprint)(config, argvMain);
74
- }
75
71
  if (command === 'help' ||
76
72
  argvMain.includes('--help') ||
77
73
  Object.keys(mainOptions).length === 0) {
@@ -119,7 +119,9 @@ const processLambda = async (argv) => {
119
119
  exports.processLambda = processLambda;
120
120
  const getAvailableFunctions = async (lambdaOptions) => {
121
121
  const lambdas = await (0, lambdaUtils_1.getAllLambdas)(lambdaOptions);
122
- (0, lambdaUtils_1.printAvailableLambdas)(lambdas, { runtimes: ['python', 'java', 'node'] });
122
+ (0, lambdaUtils_1.printAvailableLambdas)(lambdas, {
123
+ runtimes: ['python', 'java', 'node', 'dotnet']
124
+ });
123
125
  };
124
126
  exports.getAvailableFunctions = getAvailableFunctions;
125
127
  const actualProcessLambda = async (lambdaOptions) => {
@@ -10,8 +10,14 @@ const generateSbom = (config, type) => {
10
10
  if (res.statusCode === 200) {
11
11
  return res.body;
12
12
  }
13
+ else if (res.statusCode === 403) {
14
+ console.log('\nUnable to retrieve Software Bill of Materials (SBOM)');
15
+ console.log(`Please ensure OSS is enabled for your organization - org-id ${config.organizationId} and app ${config.applicationId}`);
16
+ return undefined;
17
+ }
13
18
  else {
14
19
  console.log('Unable to retrieve Software Bill of Materials (SBOM)');
20
+ return undefined;
15
21
  }
16
22
  })
17
23
  .catch((err) => {
@@ -29,6 +35,7 @@ const generateSCASbom = (config, type, reportId) => {
29
35
  }
30
36
  else {
31
37
  console.log('Unable to retrieve Software Bill of Materials (SBOM)');
38
+ return undefined;
32
39
  }
33
40
  })
34
41
  .catch((err) => {
@@ -53,9 +53,9 @@ const printFormattedOutputSca = (config, reportModelList, numberOfVulnerableLibr
53
53
  createSummaryMessageBottom(numberOfVulnerableLibraries);
54
54
  const { criticalMessage, highMessage, mediumMessage, lowMessage, noteMessage } = buildFooter(outputOrderedByLowestSeverityAndLowestNumOfCvesFirst);
55
55
  console.log(`${criticalMessage} | ${highMessage} | ${mediumMessage} | ${lowMessage} | ${noteMessage}`);
56
- if (config.host !== CE_URL) {
57
- console.log('\n' + chalk.bold('View your full dependency tree in Contrast:'));
58
- console.log(`${config.host}/Contrast/static/ng/index.html#/${config.organizationId}/applications/${config.applicationId}/libs/dependency-tree`);
56
+ if (config.host !== CE_URL && config.projectId) {
57
+ console.log('\n' + chalk.bold("Check out your project's results in Contrast"));
58
+ console.log(`${config.host}/Contrast/static/ng/index.html#/${config.organizationId}/libraries?view=static&projects=${config.name}`);
59
59
  }
60
60
  };
61
61
  function getReportTable() {
@@ -104,9 +104,9 @@ function getIssueRow(cveArray) {
104
104
  return [chalk.bold('Issue'), ':', `${cveMessagesList.join(', ')}`];
105
105
  }
106
106
  function getAdviceRow(advice) {
107
- const latestOrClosest = advice.latestStableVersion
108
- ? advice.latestStableVersion
109
- : advice.closestStableVersion;
107
+ const latestOrClosest = advice.closestStableVersion
108
+ ? advice.closestStableVersion
109
+ : advice.latestStableVersion;
110
110
  const displayAdvice = latestOrClosest
111
111
  ? `Change to version ${chalk.bold(latestOrClosest)}`
112
112
  : 'No recommendation is available according to our data. Upgrade to the latest stable is the best advice we can give.';
@@ -2,9 +2,16 @@
2
2
  const commonApi = require('../../utils/commonApi');
3
3
  const { APP_VERSION } = require('../../constants/constants');
4
4
  const requestUtils = require('../../utils/requestUtils');
5
- const scaTreeUpload = async (analysis, config) => {
5
+ const { performance } = require('perf_hooks');
6
+ const scaTreeUpload = async (analysis, config, reportSpinner) => {
7
+ if (config.projectId === '') {
8
+ console.log('We were unable to create/locate a project for this manifest, please try again or run with --debug for more information');
9
+ process.exit(1);
10
+ }
11
+ config.language = config.language === 'JAVASCRIPT' ? 'NODE' : config.language;
12
+ const startTime = performance.now();
13
+ const timeout = commonApi.getTimeout(config);
6
14
  const requestBody = {
7
- applicationId: config.applicationId,
8
15
  dependencyTree: analysis,
9
16
  organizationId: config.organizationId,
10
17
  language: config.language,
@@ -20,7 +27,7 @@ const scaTreeUpload = async (analysis, config) => {
20
27
  const reportID = await client
21
28
  .scaServiceIngest(requestBody, config)
22
29
  .then(res => {
23
- if (res.statusCode === 201) {
30
+ if (res.statusCode === 201 || res.statusCode === 200) {
24
31
  return res.body.libraryIngestJobId;
25
32
  }
26
33
  else {
@@ -38,24 +45,87 @@ const scaTreeUpload = async (analysis, config) => {
38
45
  while (keepChecking) {
39
46
  res = await client.scaServiceReportStatus(config, reportID).then(res => {
40
47
  if (config.debug) {
41
- console.log(res.statusCode);
48
+ console.log('scaServiceReportStatus', res.statusCode);
42
49
  console.log(res.body);
43
50
  }
44
51
  if (res.body.status === 'COMPLETED') {
45
52
  keepChecking = false;
46
53
  return client.scaServiceReport(config, reportID).then(res => {
47
54
  const reportBody = res.body;
48
- return { reportBody, reportID };
55
+ return { reportBody, reportId: reportID };
56
+ });
57
+ }
58
+ });
59
+ if (!keepChecking) {
60
+ return { reportArray: res.reportBody, reportId: reportID };
61
+ }
62
+ commonApi.handleTimeout(startTime, timeout, reportSpinner);
63
+ await requestUtils.sleep(5000);
64
+ }
65
+ return { reportArray: res, reportID };
66
+ };
67
+ const noProjectUpload = async (analysis, config, reportSpinner) => {
68
+ config.language = config.language === 'JAVASCRIPT' ? 'NODE' : config.language;
69
+ const startTime = performance.now();
70
+ const timeout = commonApi.getTimeout(config);
71
+ const requestBody = {
72
+ dependencyTree: analysis,
73
+ language: config.language,
74
+ tool: {
75
+ name: 'Contrast Codesec',
76
+ version: APP_VERSION
77
+ }
78
+ };
79
+ if (config.branch) {
80
+ requestBody.branchName = config.branch;
81
+ }
82
+ const client = commonApi.getHttpClient(config);
83
+ const reportID = await client
84
+ .noProjectIdUpload(requestBody, config)
85
+ .then(res => {
86
+ if (res.statusCode === 201 || res.statusCode === 200) {
87
+ return res.body.libraryIngestJobId;
88
+ }
89
+ else {
90
+ throw new Error(res.statusCode + ` error ingesting dependencies with no project id`);
91
+ }
92
+ })
93
+ .catch(err => {
94
+ throw err;
95
+ });
96
+ if (config.debug) {
97
+ console.log(' polling report no project', reportID);
98
+ }
99
+ let keepChecking = true;
100
+ let res;
101
+ while (keepChecking) {
102
+ res = await client
103
+ .scaServiceNoProjectIdReportStatus(config, reportID)
104
+ .then(res => {
105
+ if (config.debug) {
106
+ console.log('\nscaServiceReportStatus');
107
+ console.log(res.statusCode);
108
+ console.log(res.body);
109
+ }
110
+ if (res.body.status === 'COMPLETED') {
111
+ keepChecking = false;
112
+ return client
113
+ .scaServiceReportNoProjectId(config, reportID)
114
+ .then(res => {
115
+ const reportBody = res.body;
116
+ return { reportBody, reportId: reportID };
49
117
  });
50
118
  }
51
119
  });
52
120
  if (!keepChecking) {
53
- return { reportArray: res.reportBody, reportID };
121
+ return { reportArray: res.reportBody, reportId: reportID };
54
122
  }
123
+ commonApi.handleTimeout(startTime, timeout, reportSpinner);
55
124
  await requestUtils.sleep(5000);
56
125
  }
57
126
  return { reportArray: res, reportID };
58
127
  };
59
128
  module.exports = {
60
- scaTreeUpload
129
+ scaTreeUpload,
130
+ noProjectUpload
61
131
  };
@@ -3,7 +3,7 @@ const commonApi = require('../../utils/commonApi');
3
3
  const { APP_VERSION } = require('../../constants/constants');
4
4
  const commonSendSnapShot = async (analysis, config) => {
5
5
  let requestBody = {};
6
- config.experimental === true
6
+ config.legacy === false
7
7
  ? (requestBody = sendToSCAServices(config, analysis))
8
8
  : (requestBody = {
9
9
  appID: config.applicationId,
@@ -7,7 +7,7 @@ const goAnalysis = config => {
7
7
  try {
8
8
  const rawGoDependencies = goReadDepFile.getGoDependencies(config);
9
9
  const parsedGoDependencies = goParseDeps.parseGoDependencies(rawGoDependencies);
10
- if (config.experimental) {
10
+ if (config.legacy === false) {
11
11
  return parseDependenciesForSCAServices(parsedGoDependencies);
12
12
  }
13
13
  else {
@@ -4,8 +4,6 @@ const spawn = require('cross-spawn');
4
4
  const path = require('path');
5
5
  const i18n = require('i18n');
6
6
  const fs = require('fs');
7
- const readLine = require('readline');
8
- const paramHandler = require('../../utils/paramsUtil/paramHandler');
9
7
  const MAVEN = 'maven';
10
8
  const GRADLE = 'gradle';
11
9
  const determineProjectTypeAndCwd = (files, config) => {
@@ -25,26 +23,25 @@ const determineProjectTypeAndCwd = (files, config) => {
25
23
  return projectData;
26
24
  };
27
25
  const buildMaven = (config, projectData, timeout) => {
28
- let cmdStdout;
29
- try {
30
- let command = 'mvn';
31
- let args = ['dependency:tree', '-B'];
32
- if (config.mavenSettingsPath) {
33
- args.push('-s');
34
- args.push(config.mavenSettingsPath);
35
- }
36
- cmdStdout = spawn
37
- .sync(command, args, {
38
- env: process.env,
39
- cwd: projectData.cwd,
40
- timeout
41
- })
42
- .stdout.toString();
43
- return cmdStdout.toString();
26
+ let command = 'mvn';
27
+ let args = ['dependency:tree', '-B'];
28
+ if (config.mavenSettingsPath) {
29
+ args.push('-s');
30
+ args.push(config.mavenSettingsPath);
44
31
  }
45
- catch (err) {
46
- throw new Error(i18n.__('mavenDependencyTreeNonZero', projectData.cwd, `${err.message}`));
32
+ const cmdDepTree = spawn.sync(command, args, {
33
+ env: process.env,
34
+ cwd: projectData.cwd,
35
+ timeout
36
+ });
37
+ if (cmdDepTree.status !== 0) {
38
+ if (config.debug && cmdDepTree.error.code === 'ENOENT') {
39
+ console.log(`ERROR: mvn not found`);
40
+ console.log('Please make sure mvn is installed and accessible');
41
+ }
42
+ throw new Error(i18n.__('mavenDependencyTreeNonZero', projectData.cwd));
47
43
  }
44
+ return cmdDepTree.stdout.toString();
48
45
  };
49
46
  const buildGradle = (config, projectData, timeout) => {
50
47
  let cmdStdout;
@@ -96,20 +93,15 @@ const getJavaBuildDeps = (config, files) => {
96
93
  mvnDependancyTreeOutput: undefined,
97
94
  projectType: undefined
98
95
  };
99
- try {
100
- const projectData = determineProjectTypeAndCwd(files, config);
101
- if (projectData.projectType === MAVEN) {
102
- output.mvnDependancyTreeOutput = buildMaven(config, projectData, timeout);
103
- }
104
- else if (projectData.projectType === GRADLE) {
105
- output.mvnDependancyTreeOutput = buildGradle(config, projectData, timeout);
106
- }
107
- output.projectType = projectData.projectType;
108
- return output;
96
+ const projectData = determineProjectTypeAndCwd(files, config);
97
+ if (projectData.projectType === MAVEN) {
98
+ output.mvnDependancyTreeOutput = buildMaven(config, projectData, timeout);
109
99
  }
110
- catch (err) {
111
- console.log(err.message.toString());
100
+ else if (projectData.projectType === GRADLE) {
101
+ output.mvnDependancyTreeOutput = buildGradle(config, projectData, timeout);
112
102
  }
103
+ output.projectType = projectData.projectType;
104
+ return output;
113
105
  };
114
106
  module.exports = {
115
107
  getJavaBuildDeps,
@@ -8,7 +8,7 @@ const javaAnalysis = async (config, languageFiles) => {
8
8
  file.replace('build.gradle.kts', 'build.gradle');
9
9
  });
10
10
  const javaDeps = buildJavaTree(config, languageFiles.JAVA);
11
- if (config.experimental) {
11
+ if (config.legacy === false) {
12
12
  return parseDependenciesForSCAServices(javaDeps);
13
13
  }
14
14
  else {
@@ -13,7 +13,7 @@ const jsAnalysis = async (config, languageFiles) => {
13
13
  const buildNodeTree = async (config, files) => {
14
14
  let analysis = await readFiles(config, files);
15
15
  const rawNode = await parseFiles(config, files, analysis);
16
- if (config.experimental) {
16
+ if (config.legacy === false) {
17
17
  return scaServiceParser.parseJS(rawNode);
18
18
  }
19
19
  return formatMessage.createJavaScriptTSMessage(rawNode);
@@ -42,8 +42,8 @@ const parseFiles = async (config, files, js) => {
42
42
  if (!currentLockFileVersion || !npmLockFile.packages) {
43
43
  throw new Error(`package-lock.json needs to be in the NPM v2 or v3 format. \n ${generalRebuildMessage}`);
44
44
  }
45
- if (currentLockFileVersion === 3 && !config.experimental) {
46
- throw new Error(`NPM lockfileVersion 3 is only supported when using the '-e' flag.`);
45
+ if (currentLockFileVersion === 3 && config.legacy) {
46
+ throw new Error(`NPM lockfileVersion 3 is not support with --legacy`);
47
47
  }
48
48
  js.npmLockFile = await analysis.parseNpmLockFile(npmLockFile);
49
49
  }