@contrast/contrast 1.0.15 → 1.0.16
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/dist/audit/languageAnalysisEngine/sendSnapshot.js +2 -2
- package/dist/audit/report/commonReportingFunctions.js +1 -19
- package/dist/{constants.js → cliConstants.js} +41 -31
- package/dist/commands/audit/auditConfig.js +2 -2
- package/dist/commands/audit/help.js +2 -2
- package/dist/commands/auth/auth.js +1 -1
- package/dist/commands/config/config.js +1 -1
- package/dist/commands/scan/sca/scaAnalysis.js +33 -20
- package/dist/common/HTTPClient.js +4 -2
- package/dist/constants/constants.js +1 -1
- package/dist/constants/locales.js +5 -30
- package/dist/index.js +5 -5
- package/dist/scaAnalysis/common/auditReport.js +3 -2
- package/dist/scaAnalysis/common/scaParserForGoAndJava.js +1 -1
- package/dist/scaAnalysis/javascript/scaServiceParser.js +2 -2
- package/dist/scaAnalysis/php/phpNewServicesMapper.js +3 -3
- package/dist/scaAnalysis/python/analysis.js +1 -1
- package/dist/scaAnalysis/repoMode/gradleParser.js +75 -0
- package/dist/scaAnalysis/repoMode/index.js +21 -0
- package/dist/scaAnalysis/repoMode/mavenParser.js +76 -0
- package/dist/scaAnalysis/ruby/analysis.js +4 -4
- package/dist/scan/help.js +1 -1
- package/dist/scan/scanConfig.js +1 -1
- package/package.json +2 -1
- package/src/audit/languageAnalysisEngine/sendSnapshot.js +2 -6
- package/src/audit/report/commonReportingFunctions.js +1 -23
- package/src/{constants.js → cliConstants.js} +47 -35
- package/src/commands/audit/auditConfig.ts +1 -1
- package/src/commands/audit/help.ts +1 -1
- package/src/commands/auth/auth.js +1 -1
- package/src/commands/config/config.js +1 -1
- package/src/commands/scan/sca/scaAnalysis.js +35 -25
- package/src/common/HTTPClient.js +4 -2
- package/src/constants/constants.js +1 -1
- package/src/constants/locales.js +6 -44
- package/src/index.ts +1 -1
- package/src/scaAnalysis/common/auditReport.js +3 -4
- package/src/scaAnalysis/common/scaParserForGoAndJava.js +1 -1
- package/src/scaAnalysis/javascript/scaServiceParser.js +8 -2
- package/src/scaAnalysis/php/phpNewServicesMapper.js +3 -3
- package/src/scaAnalysis/python/analysis.js +1 -1
- package/src/scaAnalysis/repoMode/gradleParser.js +88 -0
- package/src/scaAnalysis/repoMode/index.js +21 -0
- package/src/scaAnalysis/repoMode/mavenParser.js +89 -0
- package/src/scaAnalysis/ruby/analysis.js +4 -4
- package/src/scan/help.js +1 -1
- package/src/scan/scanConfig.js +1 -1
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const xml2js = require('xml2js');
|
|
4
|
+
const readPomFile = project => {
|
|
5
|
+
const mavenFilePath = project.cwd + '/pom.xml';
|
|
6
|
+
const projectFile = fs.readFileSync(mavenFilePath);
|
|
7
|
+
let jsonPomFile;
|
|
8
|
+
xml2js.parseString(projectFile, (err, result) => {
|
|
9
|
+
if (err) {
|
|
10
|
+
throw err;
|
|
11
|
+
}
|
|
12
|
+
const json = JSON.stringify(result, null);
|
|
13
|
+
jsonPomFile = JSON.parse(json);
|
|
14
|
+
});
|
|
15
|
+
return jsonPomFile;
|
|
16
|
+
};
|
|
17
|
+
const getFromVersionsTag = (dependencyName, versionIdentifier, jsonPomFile) => {
|
|
18
|
+
let formattedVersion = versionIdentifier.replace(/[{}]/g, '').replace('$', '');
|
|
19
|
+
if (jsonPomFile.project.properties[0].hasOwnProperty([formattedVersion])) {
|
|
20
|
+
return jsonPomFile.project.properties[0][formattedVersion][0];
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
const parsePomFile = jsonPomFile => {
|
|
27
|
+
let dependencyTree = {};
|
|
28
|
+
let parsedVersion;
|
|
29
|
+
let dependencies;
|
|
30
|
+
jsonPomFile.project.hasOwnProperty('dependencies')
|
|
31
|
+
? (dependencies = jsonPomFile.project.dependencies[0].dependency)
|
|
32
|
+
: (dependencies =
|
|
33
|
+
jsonPomFile.project.dependencyManagement[0].dependencies[0].dependency);
|
|
34
|
+
for (let x in dependencies) {
|
|
35
|
+
let dependencyObject = dependencies[x];
|
|
36
|
+
if (!dependencyObject.hasOwnProperty('version')) {
|
|
37
|
+
parsedVersion = getVersion(jsonPomFile, dependencyObject);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
dependencyObject.version[0].includes('${versions.')
|
|
41
|
+
? (parsedVersion = getFromVersionsTag(dependencyObject.artifactId[0], dependencyObject.version[0], jsonPomFile))
|
|
42
|
+
: (parsedVersion = dependencyObject.version[0]);
|
|
43
|
+
}
|
|
44
|
+
let depName = dependencyObject.groupId +
|
|
45
|
+
'/' +
|
|
46
|
+
dependencyObject.artifactId +
|
|
47
|
+
'@' +
|
|
48
|
+
parsedVersion;
|
|
49
|
+
let parsedDependency = {
|
|
50
|
+
name: dependencyObject.artifactId[0],
|
|
51
|
+
group: dependencyObject.groupId[0],
|
|
52
|
+
version: parsedVersion,
|
|
53
|
+
directDependency: true,
|
|
54
|
+
productionDependency: true,
|
|
55
|
+
dependencies: []
|
|
56
|
+
};
|
|
57
|
+
dependencyTree[depName] = parsedDependency;
|
|
58
|
+
}
|
|
59
|
+
return dependencyTree;
|
|
60
|
+
};
|
|
61
|
+
const getVersion = (pomFile, dependencyWithoutVersion) => {
|
|
62
|
+
let parentVersion = pomFile.project.parent[0].version[0];
|
|
63
|
+
let parentGroupName = pomFile.project.parent[0].groupId[0];
|
|
64
|
+
if (parentGroupName === dependencyWithoutVersion.groupId[0]) {
|
|
65
|
+
return parentVersion;
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
module.exports = {
|
|
72
|
+
readPomFile,
|
|
73
|
+
getVersion,
|
|
74
|
+
parsePomFile,
|
|
75
|
+
getFromVersionsTag
|
|
76
|
+
};
|
|
@@ -263,25 +263,25 @@ const removeRedundantAndPopulateDefinedElements = deps => {
|
|
|
263
263
|
delete element.remote;
|
|
264
264
|
delete element.platform;
|
|
265
265
|
element.group = null;
|
|
266
|
-
element.
|
|
266
|
+
element.productionDependency = true;
|
|
267
267
|
}
|
|
268
268
|
if (element.sourceType === 'GEM') {
|
|
269
269
|
element.group = null;
|
|
270
|
-
element.
|
|
270
|
+
element.productionDependency = true;
|
|
271
271
|
delete element.sourceType;
|
|
272
272
|
delete element.remote;
|
|
273
273
|
delete element.platform;
|
|
274
274
|
}
|
|
275
275
|
if (element.sourceType === 'PATH') {
|
|
276
276
|
element.group = null;
|
|
277
|
-
element.
|
|
277
|
+
element.productionDependency = true;
|
|
278
278
|
delete element.platform;
|
|
279
279
|
delete element.sourceType;
|
|
280
280
|
delete element.remote;
|
|
281
281
|
}
|
|
282
282
|
if (element.sourceType === 'BUNDLED WITH') {
|
|
283
283
|
element.group = null;
|
|
284
|
-
element.
|
|
284
|
+
element.productionDependency = true;
|
|
285
285
|
delete element.sourceType;
|
|
286
286
|
delete element.remote;
|
|
287
287
|
delete element.branch;
|
package/dist/scan/help.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const commandLineUsage = require('command-line-usage');
|
|
3
3
|
const i18n = require('i18n');
|
|
4
|
-
const constants = require('../
|
|
4
|
+
const constants = require('../cliConstants');
|
|
5
5
|
const { commonHelpLinks } = require('../common/commonHelp');
|
|
6
6
|
const scanUsageGuide = commandLineUsage([
|
|
7
7
|
{
|
package/dist/scan/scanConfig.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const paramHandler = require('../utils/paramsUtil/paramHandler');
|
|
3
|
-
const constants = require('../
|
|
3
|
+
const constants = require('../cliConstants.js');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const { supportedLanguagesScan } = require('../constants/constants');
|
|
6
6
|
const i18n = require('i18n');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contrast/contrast",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.16",
|
|
4
4
|
"description": "Contrast Security's command line tool",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -56,6 +56,7 @@
|
|
|
56
56
|
"conf": "^10.1.2",
|
|
57
57
|
"dotenv": "^16.0.0",
|
|
58
58
|
"fast-glob": "^3.2.11",
|
|
59
|
+
"gradle-to-js": "^2.0.1",
|
|
59
60
|
"i18n": "^0.14.2",
|
|
60
61
|
"js-yaml": "^4.1.0",
|
|
61
62
|
"lodash": "^4.17.21",
|
|
@@ -29,11 +29,7 @@ const getTimeout = config => {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
const
|
|
33
|
-
config,
|
|
34
|
-
snapshotId,
|
|
35
|
-
reportSpinner
|
|
36
|
-
) => {
|
|
32
|
+
const pollForSnapshotCompletion = async (config, snapshotId, reportSpinner) => {
|
|
37
33
|
const client = commonApi.getHttpClient(config)
|
|
38
34
|
const startTime = performance.now()
|
|
39
35
|
const timeout = getTimeout(config)
|
|
@@ -76,5 +72,5 @@ const pollForSnapshotCompletition = async (
|
|
|
76
72
|
}
|
|
77
73
|
|
|
78
74
|
module.exports = {
|
|
79
|
-
|
|
75
|
+
pollForSnapshotCompletion
|
|
80
76
|
}
|
|
@@ -256,13 +256,7 @@ function buildBody(cveArray, advice) {
|
|
|
256
256
|
function getIssueRow(cveArray) {
|
|
257
257
|
orderByHighestPriority(cveArray)
|
|
258
258
|
const cveMessagesList = getIssueCveMsgList(cveArray)
|
|
259
|
-
|
|
260
|
-
const numAndSeverityTypeDesc = getNumOfAndSeverityType(cveNumbers)
|
|
261
|
-
return [
|
|
262
|
-
chalk.bold('Issue'),
|
|
263
|
-
':',
|
|
264
|
-
`${numAndSeverityTypeDesc} ${cveMessagesList.join(', ')}`
|
|
265
|
-
]
|
|
259
|
+
return [chalk.bold('Issue'), ':', `${cveMessagesList.join(', ')}`]
|
|
266
260
|
}
|
|
267
261
|
|
|
268
262
|
function gatherRemediationAdvice(guidance, libraryName, libraryVersion) {
|
|
@@ -282,21 +276,6 @@ function buildFormattedHeaderNum(contrastHeaderNum) {
|
|
|
282
276
|
return `CONTRAST-${contrastHeaderNum.toString().padStart(3, '0')}`
|
|
283
277
|
}
|
|
284
278
|
|
|
285
|
-
function getNumOfAndSeverityType(cveNumbers) {
|
|
286
|
-
const { critical, high, medium, low, note } = cveNumbers
|
|
287
|
-
|
|
288
|
-
const criticalMsg = critical > 0 ? `${critical} Critical | ` : ''
|
|
289
|
-
const highMsg = high > 0 ? `${high} High | ` : ''
|
|
290
|
-
const mediumMsg = medium > 0 ? `${medium} Medium | ` : ''
|
|
291
|
-
const lowMsg = low > 0 ? `${low} Low | ` : ''
|
|
292
|
-
const noteMsg = note > 0 ? `${note} Note` : ''
|
|
293
|
-
|
|
294
|
-
//removes/trims whitespace to single spaces
|
|
295
|
-
return `${criticalMsg} ${highMsg} ${mediumMsg} ${lowMsg} ${noteMsg}`
|
|
296
|
-
.replace(/\s+/g, ' ')
|
|
297
|
-
.trim()
|
|
298
|
-
}
|
|
299
|
-
|
|
300
279
|
const buildFooter = reportModelStructure => {
|
|
301
280
|
const { critical, high, medium, low, note } =
|
|
302
281
|
countVulnerableLibrariesBySeverity(reportModelStructure)
|
|
@@ -424,7 +403,6 @@ module.exports = {
|
|
|
424
403
|
getIssueRow,
|
|
425
404
|
gatherRemediationAdvice,
|
|
426
405
|
buildFormattedHeaderNum,
|
|
427
|
-
getNumOfAndSeverityType,
|
|
428
406
|
getIssueCveMsgList,
|
|
429
407
|
getSeverityCounts,
|
|
430
408
|
printNoVulnFoundMsg,
|
|
@@ -11,8 +11,53 @@ i18n.configure({
|
|
|
11
11
|
defaultLocale: 'en'
|
|
12
12
|
})
|
|
13
13
|
|
|
14
|
+
const sharedOptionDefinitions = [
|
|
15
|
+
{
|
|
16
|
+
name: 'proxy',
|
|
17
|
+
description:
|
|
18
|
+
'{bold ' +
|
|
19
|
+
i18n.__('constantsOptional') +
|
|
20
|
+
'}: ' +
|
|
21
|
+
i18n.__('constantsProxyServer')
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: 'key',
|
|
25
|
+
description:
|
|
26
|
+
'{bold ' +
|
|
27
|
+
i18n.__('constantsOptional') +
|
|
28
|
+
'}: ' +
|
|
29
|
+
i18n.__('constantsProxyKey')
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: 'cacert',
|
|
33
|
+
description:
|
|
34
|
+
'{bold ' +
|
|
35
|
+
i18n.__('constantsOptional') +
|
|
36
|
+
'}: ' +
|
|
37
|
+
i18n.__('constantsProxyCaCert')
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: 'cert',
|
|
41
|
+
description:
|
|
42
|
+
'{bold ' +
|
|
43
|
+
i18n.__('constantsOptional') +
|
|
44
|
+
'}: ' +
|
|
45
|
+
i18n.__('constantsProxyCert')
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: 'ignore-cert-errors',
|
|
49
|
+
type: Boolean,
|
|
50
|
+
description:
|
|
51
|
+
'{bold ' +
|
|
52
|
+
i18n.__('constantsOptional') +
|
|
53
|
+
'}:' +
|
|
54
|
+
i18n.__('constantsIgnoreCertErrors')
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
|
|
14
58
|
// CLI options that we will allow and handle
|
|
15
59
|
const scanOptionDefinitions = [
|
|
60
|
+
...sharedOptionDefinitions,
|
|
16
61
|
{
|
|
17
62
|
name: 'name',
|
|
18
63
|
alias: 'n',
|
|
@@ -100,14 +145,6 @@ const scanOptionDefinitions = [
|
|
|
100
145
|
'}: ' +
|
|
101
146
|
i18n.__('constantsHostId')
|
|
102
147
|
},
|
|
103
|
-
{
|
|
104
|
-
name: 'proxy',
|
|
105
|
-
description:
|
|
106
|
-
'{bold ' +
|
|
107
|
-
i18n.__('constantsOptional') +
|
|
108
|
-
'}: ' +
|
|
109
|
-
i18n.__('constantsProxyServer')
|
|
110
|
-
},
|
|
111
148
|
{
|
|
112
149
|
name: 'fail',
|
|
113
150
|
type: Boolean,
|
|
@@ -133,16 +170,7 @@ const scanOptionDefinitions = [
|
|
|
133
170
|
'{bold ' +
|
|
134
171
|
i18n.__('constantsOptional') +
|
|
135
172
|
'}: ' +
|
|
136
|
-
i18n.__('
|
|
137
|
-
},
|
|
138
|
-
{
|
|
139
|
-
name: 'ignore-cert-errors',
|
|
140
|
-
type: Boolean,
|
|
141
|
-
description:
|
|
142
|
-
'{bold ' +
|
|
143
|
-
i18n.__('constantsOptional') +
|
|
144
|
-
'}:' +
|
|
145
|
-
i18n.__('constantsIgnoreCertErrors')
|
|
173
|
+
i18n.__('constantsDoNotWaitForScan')
|
|
146
174
|
},
|
|
147
175
|
{
|
|
148
176
|
name: 'verbose',
|
|
@@ -214,6 +242,7 @@ const configOptionDefinitions = [
|
|
|
214
242
|
]
|
|
215
243
|
|
|
216
244
|
const auditOptionDefinitions = [
|
|
245
|
+
...sharedOptionDefinitions,
|
|
217
246
|
{
|
|
218
247
|
name: 'application-id',
|
|
219
248
|
description:
|
|
@@ -338,23 +367,6 @@ const auditOptionDefinitions = [
|
|
|
338
367
|
'}: ' +
|
|
339
368
|
i18n.__('constantsHostId')
|
|
340
369
|
},
|
|
341
|
-
{
|
|
342
|
-
name: 'proxy',
|
|
343
|
-
description:
|
|
344
|
-
'{bold ' +
|
|
345
|
-
i18n.__('constantsOptional') +
|
|
346
|
-
'}: ' +
|
|
347
|
-
i18n.__('constantsProxyServer')
|
|
348
|
-
},
|
|
349
|
-
{
|
|
350
|
-
name: 'ignore-cert-errors',
|
|
351
|
-
type: Boolean,
|
|
352
|
-
description:
|
|
353
|
-
'{bold ' +
|
|
354
|
-
i18n.__('constantsOptional') +
|
|
355
|
-
'}:' +
|
|
356
|
-
i18n.__('constantsIgnoreCertErrors')
|
|
357
|
-
},
|
|
358
370
|
{
|
|
359
371
|
name: 'save',
|
|
360
372
|
alias: 's',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import paramHandler from '../../utils/paramsUtil/paramHandler'
|
|
2
|
-
import constants from '../../
|
|
2
|
+
import constants from '../../cliConstants'
|
|
3
3
|
import { getCommandLineArgsCustom } from '../../utils/parsedCLIOptions'
|
|
4
4
|
import { ContrastConf } from '../../utils/getConfig'
|
|
5
5
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import commandLineUsage from 'command-line-usage'
|
|
2
2
|
import i18n from 'i18n'
|
|
3
|
-
import constants from '../../
|
|
3
|
+
import constants from '../../cliConstants'
|
|
4
4
|
import { commonHelpLinks } from '../../common/commonHelp'
|
|
5
5
|
|
|
6
6
|
const auditUsageGuide = commandLineUsage([
|
|
@@ -12,7 +12,7 @@ const {
|
|
|
12
12
|
} = require('../../utils/oraWrapper')
|
|
13
13
|
const { TIMEOUT, AUTH_UI_URL } = require('../../constants/constants')
|
|
14
14
|
const parsedCLIOptions = require('../../utils/parsedCLIOptions')
|
|
15
|
-
const constants = require('../../
|
|
15
|
+
const constants = require('../../cliConstants')
|
|
16
16
|
const commandLineUsage = require('command-line-usage')
|
|
17
17
|
|
|
18
18
|
const processAuth = async (argv, config) => {
|
|
@@ -1,35 +1,37 @@
|
|
|
1
|
-
const autoDetection = require('../../../scan/autoDetection')
|
|
2
|
-
const javaAnalysis = require('../../../scaAnalysis/java')
|
|
3
|
-
const treeUpload = require('../../../scaAnalysis/common/treeUpload')
|
|
4
|
-
const auditController = require('../../audit/auditController')
|
|
5
1
|
const {
|
|
6
2
|
supportedLanguages: { JAVA, GO, PYTHON, RUBY, JAVASCRIPT, NODE, PHP, DOTNET }
|
|
7
3
|
} = require('../../../constants/constants')
|
|
8
|
-
const goAnalysis = require('../../../scaAnalysis/go/goAnalysis')
|
|
9
|
-
const phpAnalysis = require('../../../scaAnalysis/php/index')
|
|
10
|
-
const { rubyAnalysis } = require('../../../scaAnalysis/ruby')
|
|
11
|
-
const { pythonAnalysis } = require('../../../scaAnalysis/python')
|
|
12
|
-
const javascriptAnalysis = require('../../../scaAnalysis/javascript')
|
|
13
4
|
const {
|
|
14
|
-
|
|
5
|
+
pollForSnapshotCompletion
|
|
15
6
|
} = require('../../../audit/languageAnalysisEngine/sendSnapshot')
|
|
16
7
|
const {
|
|
17
8
|
returnOra,
|
|
18
9
|
startSpinner,
|
|
19
10
|
succeedSpinner
|
|
20
11
|
} = require('../../../utils/oraWrapper')
|
|
21
|
-
const i18n = require('i18n')
|
|
22
12
|
const {
|
|
23
13
|
vulnerabilityReportV2
|
|
24
14
|
} = require('../../../audit/report/reportingFeature')
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
const
|
|
15
|
+
const autoDetection = require('../../../scan/autoDetection')
|
|
16
|
+
const treeUpload = require('../../../scaAnalysis/common/treeUpload')
|
|
17
|
+
const auditController = require('../../audit/auditController')
|
|
28
18
|
const rootFile = require('../../../audit/languageAnalysisEngine/getProjectRootFilenames')
|
|
29
19
|
const path = require('path')
|
|
20
|
+
const i18n = require('i18n')
|
|
21
|
+
const auditSave = require('../../../audit/save')
|
|
22
|
+
const { auditUsageGuide } = require('../../audit/help')
|
|
23
|
+
const { buildRepo } = require('../../../scaAnalysis/repoMode/index')
|
|
24
|
+
const { dotNetAnalysis } = require('../../../scaAnalysis/dotnet')
|
|
25
|
+
const { goAnalysis } = require('../../../scaAnalysis/go/goAnalysis')
|
|
26
|
+
const { phpAnalysis } = require('../../../scaAnalysis/php/index')
|
|
27
|
+
const { rubyAnalysis } = require('../../../scaAnalysis/ruby')
|
|
28
|
+
const { pythonAnalysis } = require('../../../scaAnalysis/python')
|
|
29
|
+
const javaAnalysis = require('../../../scaAnalysis/java')
|
|
30
|
+
const jsAnalysis = require('../../../scaAnalysis/javascript')
|
|
30
31
|
const auditReport = require('../../../scaAnalysis/common/auditReport')
|
|
31
32
|
const scaUpload = require('../../../scaAnalysis/common/scaServicesUpload')
|
|
32
33
|
const settingsHelper = require('../../../utils/settingsHelper')
|
|
34
|
+
const chalk = require('chalk')
|
|
33
35
|
|
|
34
36
|
const processSca = async config => {
|
|
35
37
|
//checks to see whether to use old TS / new SCA path
|
|
@@ -62,6 +64,15 @@ const processSca = async config => {
|
|
|
62
64
|
// files found looks like [ { javascript: [ Array ] } ]
|
|
63
65
|
//check we have the language and call the right analyser
|
|
64
66
|
//refactor new analyser and see if we can clean it up
|
|
67
|
+
if (config.mode === 'repo') {
|
|
68
|
+
try {
|
|
69
|
+
return buildRepo(config, filesFound[0])
|
|
70
|
+
} catch (e) {
|
|
71
|
+
console.log('Unable to build in repository mode. Check your project file')
|
|
72
|
+
process.exit(0)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
65
76
|
let messageToSend = undefined
|
|
66
77
|
if (filesFound.length === 1) {
|
|
67
78
|
switch (Object.keys(filesFound[0])[0]) {
|
|
@@ -70,10 +81,7 @@ const processSca = async config => {
|
|
|
70
81
|
config.language = JAVA
|
|
71
82
|
break
|
|
72
83
|
case JAVASCRIPT:
|
|
73
|
-
messageToSend = await
|
|
74
|
-
config,
|
|
75
|
-
filesFound[0]
|
|
76
|
-
)
|
|
84
|
+
messageToSend = await jsAnalysis.jsAnalysis(config, filesFound[0])
|
|
77
85
|
config.language = NODE
|
|
78
86
|
break
|
|
79
87
|
case PYTHON:
|
|
@@ -85,11 +93,11 @@ const processSca = async config => {
|
|
|
85
93
|
config.language = RUBY
|
|
86
94
|
break
|
|
87
95
|
case PHP:
|
|
88
|
-
messageToSend = phpAnalysis
|
|
96
|
+
messageToSend = phpAnalysis(config, filesFound[0])
|
|
89
97
|
config.language = PHP
|
|
90
98
|
break
|
|
91
99
|
case GO:
|
|
92
|
-
messageToSend = goAnalysis
|
|
100
|
+
messageToSend = goAnalysis(config, filesFound[0])
|
|
93
101
|
config.language = GO
|
|
94
102
|
break
|
|
95
103
|
case DOTNET:
|
|
@@ -137,8 +145,8 @@ const processSca = async config => {
|
|
|
137
145
|
config
|
|
138
146
|
)
|
|
139
147
|
|
|
140
|
-
//poll for completion
|
|
141
|
-
await
|
|
148
|
+
// poll for completion
|
|
149
|
+
await pollForSnapshotCompletion(
|
|
142
150
|
config,
|
|
143
151
|
snapshotResponse.id,
|
|
144
152
|
reportSpinner
|
|
@@ -162,10 +170,12 @@ const processSca = async config => {
|
|
|
162
170
|
console.log(i18n.__('languageAnalysisNoLanguageHelpLine'))
|
|
163
171
|
throw new Error()
|
|
164
172
|
} else {
|
|
173
|
+
console.log(chalk.bold(`\nMultiple language files detected \n`))
|
|
174
|
+
filesFound.forEach(file => {
|
|
175
|
+
console.log(`${Object.keys(file)[0]} : `, Object.values(file)[0])
|
|
176
|
+
})
|
|
165
177
|
throw new Error(
|
|
166
|
-
`
|
|
167
|
-
JSON.stringify(filesFound) +
|
|
168
|
-
`\nplease use --file to audit one language only. Example: contrast audit --file package-lock.json`
|
|
178
|
+
`Please use --file to audit one language only. \nExample: contrast audit --file package-lock.json`
|
|
169
179
|
)
|
|
170
180
|
}
|
|
171
181
|
}
|
package/src/common/HTTPClient.js
CHANGED
|
@@ -41,7 +41,7 @@ HTTPClient.prototype.maybeAddCertsToRequest = function (config) {
|
|
|
41
41
|
const caFileContent = fs.readFileSync(caCertFilePath)
|
|
42
42
|
if (caFileContent instanceof Error) {
|
|
43
43
|
throw new Error(
|
|
44
|
-
`Unable to read CA from
|
|
44
|
+
`Unable to read CA from ${caCertFilePath}, msg: ${caFileContent.message}`
|
|
45
45
|
)
|
|
46
46
|
}
|
|
47
47
|
this.requestOptions.ca = caFileContent
|
|
@@ -460,7 +460,9 @@ function createSnapshotURL(config) {
|
|
|
460
460
|
}
|
|
461
461
|
|
|
462
462
|
function createScaServiceReportURL(config, reportId) {
|
|
463
|
-
|
|
463
|
+
let baseUrl = `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/libraries/applications/${config.applicationId}/reports/${reportId}`
|
|
464
|
+
baseUrl = config.ignoreDev ? baseUrl.concat('?nodesToInclude=PROD') : baseUrl
|
|
465
|
+
return baseUrl
|
|
464
466
|
}
|
|
465
467
|
|
|
466
468
|
function createScaServiceReportStatusURL(config, reportId) {
|
package/src/constants/locales.js
CHANGED
|
@@ -137,7 +137,7 @@ const en_locales = () => {
|
|
|
137
137
|
constantsGradleMultiProject:
|
|
138
138
|
'Specify the sub project within your gradle application.',
|
|
139
139
|
constantsScan: 'Upload java binaries to the static scan service',
|
|
140
|
-
|
|
140
|
+
constantsDoNotWaitForScan: 'Do not wait for the result of the scan',
|
|
141
141
|
constantsProjectName:
|
|
142
142
|
'Contrast project name. If not specified, Contrast uses contrast.settings to identify the project or creates a project.',
|
|
143
143
|
constantsProjectId:
|
|
@@ -201,56 +201,19 @@ const en_locales = () => {
|
|
|
201
201
|
'After successful auth try the following command: contrast scan -f "<file>"',
|
|
202
202
|
constantsHowToRunDev3:
|
|
203
203
|
'Allowable languages are java (.jar and .war) and javascript (.js or .zip), if the language is not autodetected please use --language to specify',
|
|
204
|
-
constantsHowToRunContent1:
|
|
205
|
-
'You can run the tool on the command line and manually add the parameters, or you can put the parameters in a YAML file.',
|
|
206
|
-
constantsHowToRunContent2:
|
|
207
|
-
'If you are assessing an application that has not been instrumented by a Contrast agent you must first use the tool to register the application (Catalogue command). This will give you an application ID that you can then use in the Run Command.',
|
|
208
|
-
constantsHowToRunContent3:
|
|
209
|
-
'Allowable language values are JAVA, NODE, PYTHON, RUBY and GO.',
|
|
210
|
-
constantsManualInputHeader: 'Manual Input of Command:',
|
|
211
|
-
constantsManualInputCatalogue: 'Catalogue Command:',
|
|
212
|
-
constantsManualInputCatalogueInstruction:
|
|
213
|
-
'To analyse a new application not already instrumented by Contrast, run the following command:',
|
|
214
|
-
constantsManualInputCatalogueRun:
|
|
215
|
-
'After you run this command, you are provided a new application ID in the console. Use this ID in the Run command:',
|
|
216
|
-
constantsManualInputCatalogueRunTitle: 'Run Command:',
|
|
217
|
-
constantsManualInputCatalogueRunInstruction:
|
|
218
|
-
'To analyse an application catalogued by Contrast, run the following command:',
|
|
219
|
-
constantsYaml: 'Yaml:',
|
|
220
|
-
constantsYamlRunCommand:
|
|
221
|
-
'After you catalogue your application go to Run Command above.',
|
|
222
204
|
constantsOptions: 'Options',
|
|
223
|
-
constantsCatalogueCommand:
|
|
224
|
-
'%s YourApiKey %s YourAuthorizationKey %s YourOrganizationId %s YourHost %s YourApplicationName %s YourApplicationLanguage',
|
|
225
|
-
constantsRunCommand:
|
|
226
|
-
'%s YourApiKey %s YourAuthorizationKey %s YourOrganizationId %s YourHost %s YourApplicationId',
|
|
227
205
|
constantsSpecialCharacterWarning:
|
|
228
206
|
'Please Note: Parameters may need to be quoted to avoid issues with special characters.',
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
'Please Note: We currently do not support having a proxy server and TLS enabled at the same time.',
|
|
233
|
-
TlsHeader: 'TLS',
|
|
234
|
-
TlsBody:
|
|
235
|
-
'To enable TLS please use the YAML file with the following parameters:',
|
|
236
|
-
TlsKey: 'key: pathToKey',
|
|
237
|
-
TlsCert: 'cert: pathToCert',
|
|
238
|
-
TlsCaCert: 'cacert: pathToCaCert',
|
|
207
|
+
constantsProxyKey: 'Path to the Certificate Key',
|
|
208
|
+
constantsProxyCert: 'Path to the Cert file',
|
|
209
|
+
constantsProxyCaCert: 'Path to the CaCert file',
|
|
239
210
|
goReadProjectFile: 'Failed to read the project file @ "%s" because: "%s"',
|
|
240
|
-
goAnalysisError: 'GO analysis failed because: ',
|
|
241
|
-
goParseProjectFile: 'Failed to parse go mod graph output because: ',
|
|
242
|
-
mavenNotInstalledError:
|
|
243
|
-
"'mvn' is not available. Please ensure you have Maven installed and available on your path.",
|
|
244
211
|
mavenDependencyTreeNonZero:
|
|
245
212
|
'Building maven dependancy tree failed with a non 0 exit code',
|
|
246
213
|
gradleWrapperUnavailable:
|
|
247
214
|
'Gradle wrapper not found in root of project. Please ensure gradlew or gradlew.bat is in root of the project.',
|
|
248
215
|
gradleDependencyTreeNonZero:
|
|
249
216
|
"Building gradle dependancy tree failed with a non 0 exit code. \n Please check you have the correct version of Java installed to compile your project? \n If running against a muti module project ensure you are using the '--sub-project' flag",
|
|
250
|
-
yamlPathCamelCaseError:
|
|
251
|
-
'Warning: The "yamlPath" parameter will be deprecated in a future release. Please look at our documentation for further guidance.',
|
|
252
|
-
constantsSbom:
|
|
253
|
-
'Generate the Software Bill of Materials (SBOM) for the given application',
|
|
254
217
|
constantsMetadata:
|
|
255
218
|
'Define a set of key=value pairs (which conforms to RFC 2253) for specifying user-defined metadata associated with the application.',
|
|
256
219
|
constantsTags:
|
|
@@ -266,9 +229,7 @@ const en_locales = () => {
|
|
|
266
229
|
'Excludes developer dependencies from the results. All dependencies are included by default.',
|
|
267
230
|
constantsCommands: 'Commands',
|
|
268
231
|
constantsScanOptions: 'Scan Options',
|
|
269
|
-
sbomError: 'All required parameters are not present.',
|
|
270
232
|
sbomRetrievalError: 'Unable to retrieve Software Bill of Materials (SBOM)',
|
|
271
|
-
ignoreDevDep: 'No private libraries that are not scoped detected',
|
|
272
233
|
foundExistingProjectScan: 'Found existing project...',
|
|
273
234
|
projectCreatedScan: 'Project created',
|
|
274
235
|
uploadingScan: 'Uploading file to scan.',
|
|
@@ -284,7 +245,6 @@ const en_locales = () => {
|
|
|
284
245
|
specifyFileAuditNotFound: 'No files found for library analysis',
|
|
285
246
|
populateProjectIdMessage: 'project ID is %s',
|
|
286
247
|
genericServiceError: 'returned with status code %s',
|
|
287
|
-
projectIdError: 'Your project ID is %s please check this is correct',
|
|
288
248
|
permissionsError:
|
|
289
249
|
'You do not have the correct permissions here. \n Contact support@contrastsecurity.com to get this fixed.',
|
|
290
250
|
scanErrorFileMessage:
|
|
@@ -446,6 +406,8 @@ const en_locales = () => {
|
|
|
446
406
|
auditBadFiletypeSpecifiedForSave: `\n ${chalk.yellow.bold(
|
|
447
407
|
'Bad file type specified for --save option. Use audit --help to see valid --save options.'
|
|
448
408
|
)}`,
|
|
409
|
+
auditServicesMessageForTS:
|
|
410
|
+
'View your vulnerable library list or full dependency tree in Contrast:',
|
|
449
411
|
auditReportWaiting: 'Waiting for report...',
|
|
450
412
|
auditReportFail: 'Report Retrieval Failed, please try again',
|
|
451
413
|
auditReportSuccessMessage: 'Report successfully retrieved',
|
package/src/index.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { processAudit } from './commands/audit/processAudit'
|
|
|
5
5
|
import { processAuth } from './commands/auth/auth'
|
|
6
6
|
import { processConfig } from './commands/config/config'
|
|
7
7
|
import { processScan } from './commands/scan/processScan'
|
|
8
|
-
import constants from './
|
|
8
|
+
import constants from './cliConstants'
|
|
9
9
|
import { APP_NAME, APP_VERSION } from './constants/constants'
|
|
10
10
|
import { processLambda } from './lambda/lambda'
|
|
11
11
|
import { localConfig } from './utils/getConfig'
|
|
@@ -11,6 +11,7 @@ const { assignBySeverity } = require('../../scan/formatScanOutput')
|
|
|
11
11
|
const chalk = require('chalk')
|
|
12
12
|
const { CE_URL } = require('../../constants/constants')
|
|
13
13
|
const common = require('../../common/fail')
|
|
14
|
+
const i18n = require('i18n')
|
|
14
15
|
|
|
15
16
|
const processAuditReport = (config, results) => {
|
|
16
17
|
let severityCounts = {}
|
|
@@ -92,11 +93,9 @@ const formatScaServicesReport = (config, results) => {
|
|
|
92
93
|
printVulnInfo(projectOverviewCount)
|
|
93
94
|
|
|
94
95
|
if (config.host !== CE_URL) {
|
|
96
|
+
console.log('\n' + chalk.bold(i18n.__('auditServicesMessageForTS')))
|
|
95
97
|
console.log(
|
|
96
|
-
|
|
97
|
-
)
|
|
98
|
-
console.log(
|
|
99
|
-
`${config.host}/Contrast/static/ng/index.html#/${config.organizationId}/applications/${config.applicationId}/libs/dependency-tree`
|
|
98
|
+
`${config.host}/Contrast/static/ng/index.html#/${config.organizationId}/applications/${config.applicationId}/libs`
|
|
100
99
|
)
|
|
101
100
|
}
|
|
102
101
|
return projectOverviewCount
|
|
@@ -12,7 +12,7 @@ const parseDependenciesForSCAServices = dependencyTreeObject => {
|
|
|
12
12
|
group: unParsedDependencyTree[dependency].group,
|
|
13
13
|
version: unParsedDependencyTree[dependency].version,
|
|
14
14
|
directDependency: unParsedDependencyTree[dependency].type === 'direct',
|
|
15
|
-
|
|
15
|
+
productionDependency: true,
|
|
16
16
|
dependencies: subDeps
|
|
17
17
|
}
|
|
18
18
|
parsedDependencyTree[dependency] = parsedDependency
|