@contrast/contrast 1.0.23 → 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.
- package/README.md +21 -138
- package/dist/audit/languageAnalysisEngine/sendSnapshot.js +2 -19
- package/dist/audit/save.js +6 -1
- package/dist/cliConstants.js +29 -0
- package/dist/commands/audit/auditController.js +2 -1
- package/dist/commands/audit/help.js +3 -2
- package/dist/commands/audit/processAudit.js +2 -0
- package/dist/commands/audit/saveFile.js +5 -1
- package/dist/commands/github/projectGroup.js +164 -0
- package/dist/common/HTTPClient.js +165 -13
- package/dist/constants/constants.js +3 -5
- package/dist/constants/locales.js +7 -3
- package/dist/index.js +0 -4
- package/dist/lambda/lambda.js +3 -1
- package/dist/scaAnalysis/common/commonReportingFunctionsSca.js +3 -3
- package/dist/scaAnalysis/common/scaServicesUpload.js +77 -7
- package/dist/scaAnalysis/common/treeUpload.js +19 -5
- package/dist/scaAnalysis/go/goAnalysis.js +6 -1
- package/dist/scaAnalysis/java/index.js +6 -1
- package/dist/scaAnalysis/javascript/index.js +5 -2
- package/dist/scaAnalysis/legacy/legacyFlow.js +33 -0
- package/dist/scaAnalysis/php/index.js +8 -2
- package/dist/scaAnalysis/processServicesFlow.js +21 -0
- package/dist/scaAnalysis/python/analysis.js +10 -4
- package/dist/scaAnalysis/python/index.js +6 -1
- package/dist/scaAnalysis/repoMode/index.js +2 -2
- package/dist/scaAnalysis/ruby/analysis.js +10 -1
- package/dist/scaAnalysis/ruby/index.js +6 -1
- package/dist/scaAnalysis/scaAnalysis.js +47 -25
- package/dist/scan/autoDetection.js +41 -2
- package/dist/scan/fileUtils.js +5 -4
- package/dist/utils/commonApi.js +26 -1
- package/dist/utils/settingsHelper.js +14 -0
- package/package.json +8 -5
- package/src/audit/languageAnalysisEngine/sendSnapshot.js +3 -22
- package/src/audit/save.js +10 -1
- package/src/cliConstants.js +32 -0
- package/src/commands/audit/auditController.js +2 -1
- package/src/commands/audit/help.js +3 -2
- package/src/commands/audit/processAudit.js +2 -0
- package/src/commands/audit/saveFile.js +6 -1
- package/src/commands/github/projectGroup.js +187 -0
- package/src/common/HTTPClient.js +221 -13
- package/src/constants/constants.js +3 -5
- package/src/constants/locales.js +9 -3
- package/src/index.ts +0 -5
- package/src/lambda/lambda.ts +3 -1
- package/src/lambda/lambdaUtils.ts +1 -1
- package/src/scaAnalysis/common/commonReportingFunctionsSca.js +3 -3
- package/src/scaAnalysis/common/scaServicesUpload.js +92 -7
- package/src/scaAnalysis/common/treeUpload.js +20 -5
- package/src/scaAnalysis/go/goAnalysis.js +6 -1
- package/src/scaAnalysis/java/index.js +6 -1
- package/src/scaAnalysis/javascript/index.js +6 -4
- package/src/scaAnalysis/legacy/legacyFlow.js +48 -0
- package/src/scaAnalysis/php/index.js +8 -2
- package/src/scaAnalysis/processServicesFlow.js +29 -0
- package/src/scaAnalysis/python/analysis.js +10 -4
- package/src/scaAnalysis/python/index.js +6 -1
- package/src/scaAnalysis/repoMode/index.js +2 -2
- package/src/scaAnalysis/ruby/analysis.js +11 -1
- package/src/scaAnalysis/ruby/index.js +6 -1
- package/src/scaAnalysis/scaAnalysis.js +61 -37
- package/src/scan/autoDetection.js +44 -3
- package/src/scan/fileUtils.js +5 -4
- package/src/utils/commonApi.js +29 -1
- package/src/utils/settingsHelper.js +16 -0
- package/dist/commands/fingerprint/processFingerprint.js +0 -14
- package/src/commands/fingerprint/processFingerprint.js +0 -21
- /package/dist/commands/{fingerprint → github}/fingerprintConfig.js +0 -0
- /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.
|
|
194
|
+
HTTPClient.prototype.scaServiceReportNoProjectId = function scaServiceReport(config, reportId) {
|
|
183
195
|
const options = _.cloneDeep(this.requestOptions);
|
|
184
|
-
|
|
185
|
-
|
|
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.
|
|
202
|
+
HTTPClient.prototype.scaServiceReportStatus = function scaServiceReport(config, reportId) {
|
|
189
203
|
const options = _.cloneDeep(this.requestOptions);
|
|
190
|
-
|
|
191
|
-
|
|
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}/
|
|
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}/
|
|
450
|
+
return `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/libraries/ingests/${reportId}/status`;
|
|
347
451
|
}
|
|
348
|
-
function
|
|
349
|
-
return `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/
|
|
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
|
|
356
|
-
|
|
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
|
|
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 = '
|
|
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 = '
|
|
31
|
-
const SBOM_SPDX_FILE = '
|
|
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
|
|
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: '
|
|
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
|
|
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) {
|
package/dist/lambda/lambda.js
CHANGED
|
@@ -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, {
|
|
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) => {
|
|
@@ -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(
|
|
58
|
-
console.log(`${config.host}/Contrast/static/ng/index.html#/${config.organizationId}/
|
|
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() {
|
|
@@ -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
|
|
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,11 +3,13 @@ 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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
config.legacy === false
|
|
7
|
+
? (requestBody = sendToSCAServices(config, analysis))
|
|
8
|
+
: (requestBody = {
|
|
9
|
+
appID: config.applicationId,
|
|
10
|
+
cliVersion: APP_VERSION,
|
|
11
|
+
snapshot: analysis
|
|
12
|
+
});
|
|
11
13
|
const client = commonApi.getHttpClient(config);
|
|
12
14
|
return client
|
|
13
15
|
.sendSnapshot(requestBody, config)
|
|
@@ -26,6 +28,18 @@ const commonSendSnapShot = async (analysis, config) => {
|
|
|
26
28
|
throw err;
|
|
27
29
|
});
|
|
28
30
|
};
|
|
31
|
+
const sendToSCAServices = (config, analysis) => {
|
|
32
|
+
return {
|
|
33
|
+
applicationId: config.applicationId,
|
|
34
|
+
dependencyTree: analysis,
|
|
35
|
+
organizationId: config.organizationId,
|
|
36
|
+
language: config.language,
|
|
37
|
+
tool: {
|
|
38
|
+
name: 'Contrast Codesec',
|
|
39
|
+
version: APP_VERSION
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
};
|
|
29
43
|
module.exports = {
|
|
30
44
|
commonSendSnapShot
|
|
31
45
|
};
|
|
@@ -7,7 +7,12 @@ const goAnalysis = config => {
|
|
|
7
7
|
try {
|
|
8
8
|
const rawGoDependencies = goReadDepFile.getGoDependencies(config);
|
|
9
9
|
const parsedGoDependencies = goParseDeps.parseGoDependencies(rawGoDependencies);
|
|
10
|
-
|
|
10
|
+
if (config.legacy === false) {
|
|
11
|
+
return parseDependenciesForSCAServices(parsedGoDependencies);
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
return createGoTSMessage(parsedGoDependencies);
|
|
15
|
+
}
|
|
11
16
|
}
|
|
12
17
|
catch (e) {
|
|
13
18
|
console.log(e.message.toString());
|
|
@@ -8,7 +8,12 @@ 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
|
-
|
|
11
|
+
if (config.legacy === false) {
|
|
12
|
+
return parseDependenciesForSCAServices(javaDeps);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
return createJavaTSMessage(javaDeps);
|
|
16
|
+
}
|
|
12
17
|
};
|
|
13
18
|
const buildJavaTree = (config, files) => {
|
|
14
19
|
const javaBuildDeps = analysis.getJavaBuildDeps(config, files);
|
|
@@ -13,6 +13,9 @@ 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.legacy === false) {
|
|
17
|
+
return scaServiceParser.parseJS(rawNode);
|
|
18
|
+
}
|
|
16
19
|
return formatMessage.createJavaScriptTSMessage(rawNode);
|
|
17
20
|
};
|
|
18
21
|
const readFiles = async (config, files) => {
|
|
@@ -39,8 +42,8 @@ const parseFiles = async (config, files, js) => {
|
|
|
39
42
|
if (!currentLockFileVersion || !npmLockFile.packages) {
|
|
40
43
|
throw new Error(`package-lock.json needs to be in the NPM v2 or v3 format. \n ${generalRebuildMessage}`);
|
|
41
44
|
}
|
|
42
|
-
if (currentLockFileVersion === 3) {
|
|
43
|
-
throw new Error(`NPM lockfileVersion 3 is
|
|
45
|
+
if (currentLockFileVersion === 3 && config.legacy) {
|
|
46
|
+
throw new Error(`NPM lockfileVersion 3 is not support with --legacy`);
|
|
44
47
|
}
|
|
45
48
|
js.npmLockFile = await analysis.parseNpmLockFile(npmLockFile);
|
|
46
49
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const auditController = require('../../commands/audit/auditController');
|
|
3
|
+
const { returnOra, startSpinner, succeedSpinner } = require('../../utils/oraWrapper');
|
|
4
|
+
const i18n = require('i18n');
|
|
5
|
+
const treeUpload = require('../common/treeUpload');
|
|
6
|
+
const { pollForSnapshotCompletion } = require('../../audit/languageAnalysisEngine/sendSnapshot');
|
|
7
|
+
const { vulnerabilityReportV2 } = require('../../audit/report/reportingFeature');
|
|
8
|
+
const { auditSave } = require('../../audit/save');
|
|
9
|
+
const legacyFlow = async (config, messageToSend) => {
|
|
10
|
+
const startTime = performance.now();
|
|
11
|
+
if (!config.applicationId) {
|
|
12
|
+
config.applicationId = await auditController.dealWithNoAppId(config);
|
|
13
|
+
}
|
|
14
|
+
console.log('');
|
|
15
|
+
const reportSpinner = returnOra(i18n.__('auditSCAAnalysisBegins'));
|
|
16
|
+
startSpinner(reportSpinner);
|
|
17
|
+
const snapshotResponse = await treeUpload.commonSendSnapShot(messageToSend, config);
|
|
18
|
+
await pollForSnapshotCompletion(config, snapshotResponse.id, reportSpinner);
|
|
19
|
+
succeedSpinner(reportSpinner, i18n.__('auditSCAAnalysisComplete'));
|
|
20
|
+
await vulnerabilityReportV2(config, snapshotResponse.id);
|
|
21
|
+
if (config.save !== undefined) {
|
|
22
|
+
await auditSave(config);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
console.log('\nUse contrast audit --save to generate an SBOM');
|
|
26
|
+
}
|
|
27
|
+
const endTime = performance.now() - startTime;
|
|
28
|
+
const scanDurationMs = endTime - startTime;
|
|
29
|
+
console.log(`----- completed in ${(scanDurationMs / 1000).toFixed(2)}s -----`);
|
|
30
|
+
};
|
|
31
|
+
module.exports = {
|
|
32
|
+
legacyFlow
|
|
33
|
+
};
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const { readFile, parseProjectFiles } = require('./analysis');
|
|
3
3
|
const { createPhpTSMessage } = require('../common/formatMessage');
|
|
4
|
+
const { parsePHPLockFileForScaServices } = require('./phpNewServicesMapper');
|
|
4
5
|
const phpAnalysis = config => {
|
|
5
6
|
let analysis = readFiles(config);
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
if (config.legacy === false) {
|
|
8
|
+
return parsePHPLockFileForScaServices(analysis.rawLockFileContents);
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
const phpDep = parseProjectFiles(analysis);
|
|
12
|
+
return createPhpTSMessage(phpDep);
|
|
13
|
+
}
|
|
8
14
|
};
|
|
9
15
|
const readFiles = config => {
|
|
10
16
|
let php = {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const projectConfig = require('../commands/github/projectGroup');
|
|
3
|
+
const scaServicesUpload = require('../scaAnalysis/common/scaServicesUpload');
|
|
4
|
+
const processUpload = async (analysis, config, reportSpinner) => {
|
|
5
|
+
let projectId = await projectConfig.getProjectIdByOrg(config);
|
|
6
|
+
if (projectId === '') {
|
|
7
|
+
if (config.track === true) {
|
|
8
|
+
await projectConfig.registerNewProjectGroup(config);
|
|
9
|
+
projectId = await projectConfig.getProjectIdByOrg(config);
|
|
10
|
+
}
|
|
11
|
+
if (config.track === false || config.track === undefined) {
|
|
12
|
+
return await scaServicesUpload.noProjectUpload(analysis, config, reportSpinner);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
await projectConfig.registerProjectIdOnCliServices(config, projectId);
|
|
16
|
+
config.projectId = projectId;
|
|
17
|
+
return await scaServicesUpload.scaTreeUpload(analysis, config, reportSpinner);
|
|
18
|
+
};
|
|
19
|
+
module.exports = {
|
|
20
|
+
processUpload
|
|
21
|
+
};
|
|
@@ -48,10 +48,16 @@ const checkForCorrectFiles = languageFiles => {
|
|
|
48
48
|
};
|
|
49
49
|
const getPythonDeps = (config, languageFiles) => {
|
|
50
50
|
try {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
if (config.legacy === false) {
|
|
52
|
+
let pythonLockFileContents = readLockFile(config.file);
|
|
53
|
+
return scaPythonParser(pythonLockFileContents);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
checkForCorrectFiles(languageFiles);
|
|
57
|
+
const parseProject = readAndParseProjectFile(config.file);
|
|
58
|
+
const parsePip = readAndParseLockFile(config.file);
|
|
59
|
+
return { pipfileLock: parsePip, pipfilDependanceies: parseProject };
|
|
60
|
+
}
|
|
55
61
|
}
|
|
56
62
|
catch (err) {
|
|
57
63
|
console.log(err.message.toString());
|