@contrast/contrast 1.0.21 → 1.0.23
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/report/commonReportingFunctions.js +1 -1
- package/dist/audit/save.js +10 -4
- package/dist/cliConstants.js +4 -3
- package/dist/commands/audit/help.js +3 -1
- package/dist/commands/audit/processAudit.js +1 -1
- package/dist/commands/auth/auth.js +5 -0
- package/dist/commands/learn/processLearn.js +1 -1
- package/dist/common/HTTPClient.js +9 -0
- package/dist/constants/constants.js +1 -1
- package/dist/constants/lambda.js +1 -0
- package/dist/constants/locales.js +15 -14
- package/dist/lambda/help.js +3 -0
- package/dist/lambda/scanRequest.js +12 -1
- package/dist/sbom/generateSbom.js +7 -0
- package/dist/scaAnalysis/common/commonReportingFunctionsSca.js +3 -3
- package/dist/scaAnalysis/common/treeUpload.js +8 -19
- package/dist/scaAnalysis/go/goAnalysis.js +1 -6
- package/dist/scaAnalysis/java/analysis.js +24 -32
- package/dist/scaAnalysis/java/index.js +1 -6
- package/dist/scaAnalysis/javascript/analysis.js +11 -33
- package/dist/scaAnalysis/javascript/index.js +14 -4
- package/dist/scaAnalysis/javascript/scaServiceParser.js +3 -3
- package/dist/scaAnalysis/php/index.js +2 -8
- package/dist/scaAnalysis/python/analysis.js +4 -10
- package/dist/scaAnalysis/python/index.js +1 -6
- package/dist/scaAnalysis/ruby/analysis.js +1 -10
- package/dist/scaAnalysis/ruby/index.js +1 -6
- package/dist/scaAnalysis/scaAnalysis.js +17 -59
- package/dist/scan/help.js +3 -0
- package/package.json +2 -5
- package/src/audit/report/commonReportingFunctions.js +1 -1
- package/src/audit/save.js +11 -9
- package/src/cliConstants.js +4 -3
- package/src/commands/audit/help.js +3 -1
- package/src/commands/audit/processAudit.js +2 -5
- package/src/commands/auth/auth.js +5 -0
- package/src/commands/learn/processLearn.js +1 -1
- package/src/common/HTTPClient.js +11 -0
- package/src/constants/constants.js +1 -1
- package/src/constants/lambda.js +1 -0
- package/src/constants/locales.js +15 -14
- package/src/index.ts +0 -1
- package/src/lambda/help.ts +3 -0
- package/src/lambda/scanRequest.ts +27 -2
- package/src/sbom/generateSbom.ts +8 -0
- package/src/scaAnalysis/common/commonReportingFunctionsSca.js +3 -3
- package/src/scaAnalysis/common/treeUpload.js +12 -20
- package/src/scaAnalysis/go/goAnalysis.js +1 -6
- package/src/scaAnalysis/java/analysis.js +29 -34
- package/src/scaAnalysis/java/index.js +1 -6
- package/src/scaAnalysis/javascript/analysis.js +19 -34
- package/src/scaAnalysis/javascript/index.js +27 -4
- package/src/scaAnalysis/javascript/scaServiceParser.js +3 -3
- package/src/scaAnalysis/php/index.js +2 -8
- package/src/scaAnalysis/python/analysis.js +4 -10
- package/src/scaAnalysis/python/index.js +1 -6
- package/src/scaAnalysis/ruby/analysis.js +1 -11
- package/src/scaAnalysis/ruby/index.js +1 -6
- package/src/scaAnalysis/scaAnalysis.js +25 -85
- package/src/scan/help.js +3 -0
- package/dist/utils/settingsHelper.js +0 -24
- package/src/utils/settingsHelper.js +0 -26
|
@@ -3,12 +3,7 @@ const { createPythonTSMessage } = require('../common/formatMessage');
|
|
|
3
3
|
const { getPythonDeps, secondaryParser } = require('./analysis');
|
|
4
4
|
const pythonAnalysis = (config, languageFiles) => {
|
|
5
5
|
const pythonDeps = getPythonDeps(config, languageFiles.PYTHON);
|
|
6
|
-
|
|
7
|
-
return pythonDeps;
|
|
8
|
-
}
|
|
9
|
-
else {
|
|
10
|
-
return createPythonTSMessage(pythonDeps);
|
|
11
|
-
}
|
|
6
|
+
return createPythonTSMessage(pythonDeps);
|
|
12
7
|
};
|
|
13
8
|
module.exports = {
|
|
14
9
|
pythonAnalysis
|
|
@@ -6,16 +6,7 @@ const getRubyDeps = (config, languageFiles) => {
|
|
|
6
6
|
checkForCorrectFiles(languageFiles);
|
|
7
7
|
const parsedGem = readAndParseGemfile(config.file);
|
|
8
8
|
const parsedLock = readAndParseGemLockFile(config.file);
|
|
9
|
-
|
|
10
|
-
const rubyArray = removeRedundantAndPopulateDefinedElements(parsedLock.sources);
|
|
11
|
-
let rubyTree = createRubyTree(rubyArray);
|
|
12
|
-
findChildrenDependencies(rubyTree);
|
|
13
|
-
processRootDependencies(parsedLock.dependencies, rubyTree);
|
|
14
|
-
return rubyTree;
|
|
15
|
-
}
|
|
16
|
-
else {
|
|
17
|
-
return { gemfilesDependanceies: parsedGem, gemfileLock: parsedLock };
|
|
18
|
-
}
|
|
9
|
+
return { gemfilesDependanceies: parsedGem, gemfileLock: parsedLock };
|
|
19
10
|
}
|
|
20
11
|
catch (err) {
|
|
21
12
|
throw err;
|
|
@@ -3,12 +3,7 @@ const analysis = require('./analysis');
|
|
|
3
3
|
const { createRubyTSMessage } = require('../common/formatMessage');
|
|
4
4
|
const rubyAnalysis = (config, languageFiles) => {
|
|
5
5
|
const rubyDeps = analysis.getRubyDeps(config, languageFiles.RUBY);
|
|
6
|
-
|
|
7
|
-
return rubyDeps;
|
|
8
|
-
}
|
|
9
|
-
else {
|
|
10
|
-
return createRubyTSMessage(rubyDeps);
|
|
11
|
-
}
|
|
6
|
+
return createRubyTSMessage(rubyDeps);
|
|
12
7
|
};
|
|
13
8
|
module.exports = {
|
|
14
9
|
rubyAnalysis
|
|
@@ -19,14 +19,8 @@ const { rubyAnalysis } = require('./ruby');
|
|
|
19
19
|
const { pythonAnalysis } = require('./python');
|
|
20
20
|
const javaAnalysis = require('./java');
|
|
21
21
|
const jsAnalysis = require('./javascript');
|
|
22
|
-
const auditReport = require('./common/auditReport');
|
|
23
|
-
const scaUpload = require('./common/scaServicesUpload');
|
|
24
|
-
const settingsHelper = require('../utils/settingsHelper');
|
|
25
22
|
const chalk = require('chalk');
|
|
26
|
-
const saveResults = require('../scan/saveResults');
|
|
27
|
-
const { convertGenericToTypedReportModelSca } = require('./common/utils/reportUtilsSca');
|
|
28
23
|
const processSca = async (config) => {
|
|
29
|
-
config = await settingsHelper.getSettings(config);
|
|
30
24
|
const startTime = performance.now();
|
|
31
25
|
let filesFound;
|
|
32
26
|
if (config.help) {
|
|
@@ -49,17 +43,7 @@ const processSca = async (config) => {
|
|
|
49
43
|
switch (Object.keys(filesFound[0])[0]) {
|
|
50
44
|
case JAVA:
|
|
51
45
|
config.language = JAVA;
|
|
52
|
-
|
|
53
|
-
try {
|
|
54
|
-
return repoMode.buildRepo(config, filesFound[0]);
|
|
55
|
-
}
|
|
56
|
-
catch (e) {
|
|
57
|
-
throw new Error('Unable to build in repository mode. Check your project file');
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
messageToSend = await javaAnalysis.javaAnalysis(config, filesFound[0]);
|
|
62
|
-
}
|
|
46
|
+
messageToSend = await javaAnalysis.javaAnalysis(config, filesFound[0]);
|
|
63
47
|
break;
|
|
64
48
|
case JAVASCRIPT:
|
|
65
49
|
messageToSend = await jsAnalysis.jsAnalysis(config, filesFound[0]);
|
|
@@ -82,15 +66,9 @@ const processSca = async (config) => {
|
|
|
82
66
|
config.language = GO;
|
|
83
67
|
break;
|
|
84
68
|
case DOTNET:
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
messageToSend = dotNetAnalysis(config, filesFound[0]);
|
|
91
|
-
config.language = DOTNET;
|
|
92
|
-
break;
|
|
93
|
-
}
|
|
69
|
+
messageToSend = dotNetAnalysis(config, filesFound[0]);
|
|
70
|
+
config.language = DOTNET;
|
|
71
|
+
break;
|
|
94
72
|
default:
|
|
95
73
|
console.log('No supported language detected in project path');
|
|
96
74
|
return;
|
|
@@ -98,42 +76,22 @@ const processSca = async (config) => {
|
|
|
98
76
|
if (!config.applicationId) {
|
|
99
77
|
config.applicationId = await auditController.dealWithNoAppId(config);
|
|
100
78
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
await auditSave.auditSave(config, reportId);
|
|
111
|
-
}
|
|
112
|
-
else {
|
|
113
|
-
console.log('Use contrast audit --save to generate an SBOM');
|
|
114
|
-
}
|
|
115
|
-
const endTime = performance.now() - startTime;
|
|
116
|
-
const scanDurationMs = endTime - startTime;
|
|
117
|
-
console.log(`----- completed in ${(scanDurationMs / 1000).toFixed(2)}s -----`);
|
|
79
|
+
console.log('');
|
|
80
|
+
const reportSpinner = returnOra(i18n.__('auditSCAAnalysisBegins'));
|
|
81
|
+
startSpinner(reportSpinner);
|
|
82
|
+
const snapshotResponse = await treeUpload.commonSendSnapShot(messageToSend, config);
|
|
83
|
+
await pollForSnapshotCompletion(config, snapshotResponse.id, reportSpinner);
|
|
84
|
+
succeedSpinner(reportSpinner, i18n.__('auditSCAAnalysisComplete'));
|
|
85
|
+
await vulnerabilityReportV2(config, snapshotResponse.id);
|
|
86
|
+
if (config.save !== undefined) {
|
|
87
|
+
await auditSave.auditSave(config);
|
|
118
88
|
}
|
|
119
89
|
else {
|
|
120
|
-
console.log('');
|
|
121
|
-
const reportSpinner = returnOra(i18n.__('auditSCAAnalysisBegins'));
|
|
122
|
-
startSpinner(reportSpinner);
|
|
123
|
-
const snapshotResponse = await treeUpload.commonSendSnapShot(messageToSend, config);
|
|
124
|
-
await pollForSnapshotCompletion(config, snapshotResponse.id, reportSpinner);
|
|
125
|
-
succeedSpinner(reportSpinner, i18n.__('auditSCAAnalysisComplete'));
|
|
126
|
-
await vulnerabilityReportV2(config, snapshotResponse.id);
|
|
127
|
-
if (config.save !== undefined) {
|
|
128
|
-
await auditSave.auditSave(config);
|
|
129
|
-
}
|
|
130
|
-
else {
|
|
131
|
-
console.log('\nUse contrast audit --save to generate an SBOM');
|
|
132
|
-
}
|
|
133
|
-
const endTime = performance.now() - startTime;
|
|
134
|
-
const scanDurationMs = endTime - startTime;
|
|
135
|
-
console.log(`----- completed in ${(scanDurationMs / 1000).toFixed(2)}s -----`);
|
|
90
|
+
console.log('\nUse contrast audit --save to generate an SBOM');
|
|
136
91
|
}
|
|
92
|
+
const endTime = performance.now() - startTime;
|
|
93
|
+
const scanDurationMs = endTime - startTime;
|
|
94
|
+
console.log(`----- completed in ${(scanDurationMs / 1000).toFixed(2)}s -----`);
|
|
137
95
|
}
|
|
138
96
|
else {
|
|
139
97
|
if (filesFound.length === 0) {
|
package/dist/scan/help.js
CHANGED
|
@@ -4,6 +4,9 @@ const i18n = require('i18n');
|
|
|
4
4
|
const constants = require('../cliConstants');
|
|
5
5
|
const { commonHelpLinks } = require('../common/commonHelp');
|
|
6
6
|
const scanUsageGuide = commandLineUsage([
|
|
7
|
+
{
|
|
8
|
+
header: i18n.__('constantsHeader')
|
|
9
|
+
},
|
|
7
10
|
{
|
|
8
11
|
header: i18n.__('scanHeader')
|
|
9
12
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contrast/contrast",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.23",
|
|
4
4
|
"description": "Contrast Security's command line tool",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -27,12 +27,9 @@
|
|
|
27
27
|
"test": "jest --testPathIgnorePatterns=./test-integration/",
|
|
28
28
|
"test-int": "jest ./test-integration/",
|
|
29
29
|
"test-int-scan": "jest ./test-integration/scan",
|
|
30
|
-
"test-int-audit": "jest test-integration/audit",
|
|
31
|
-
"test-int-audit-reports": "jest test-integration/audit/audit-language-reports.spec.js",
|
|
32
30
|
"test-int-scan-errors": "jest test-integration/scan/scanLocalErrors.spec.js",
|
|
33
31
|
"test-int-scan-reports": "jest test-integration/scan/scanReport.spec.js",
|
|
34
|
-
"test-int-audit-features": "jest test-integration/audit/auditFeatures
|
|
35
|
-
"test-int-audit-experimental": "jest test-integration/audit/audit-experimental.spec.js",
|
|
32
|
+
"test-int-audit-features": "jest test-integration/audit/auditFeatures",
|
|
36
33
|
"format": "prettier --write \"**/*.{ts,tsx,js,json,md,yml}\" .eslintrc.*",
|
|
37
34
|
"check-format": "prettier --check \"**/*.{ts,tsx,js,json,md,yml}\" .eslintrc.*",
|
|
38
35
|
"coverage-local": "nyc --reporter=text mocha './test/**/*.spec.js'",
|
|
@@ -247,7 +247,7 @@ function buildBody(cveArray, advice) {
|
|
|
247
247
|
//todo different advice based on remediationGuidance being available or now
|
|
248
248
|
// console.log(advice)
|
|
249
249
|
|
|
250
|
-
const minOrMax = advice.
|
|
250
|
+
const minOrMax = advice.minimum ? advice.minimum : advice.maximum
|
|
251
251
|
const displayAdvice = minOrMax
|
|
252
252
|
? `Change to version ${chalk.bold(minOrMax)}`
|
|
253
253
|
: 'No recommendation is available according to our data. Upgrade to the latest stable is the best advice we can give.'
|
package/src/audit/save.js
CHANGED
|
@@ -23,18 +23,20 @@ async function auditSave(config, reportId) {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
if (fileFormat) {
|
|
26
|
-
if (config.
|
|
27
|
-
|
|
26
|
+
if (config.legacy === false) {
|
|
27
|
+
const sbomResponse = await sbom.generateSCASbom(
|
|
28
28
|
config,
|
|
29
29
|
fileFormat,
|
|
30
|
-
|
|
30
|
+
reportId
|
|
31
31
|
)
|
|
32
|
+
if (sbomResponse) {
|
|
33
|
+
save.saveFile(config, fileFormat, sbomResponse)
|
|
34
|
+
}
|
|
32
35
|
} else {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
fileFormat,
|
|
36
|
-
|
|
37
|
-
)
|
|
36
|
+
const sbomResponse = await sbom.generateSbom(config, fileFormat)
|
|
37
|
+
if (sbomResponse) {
|
|
38
|
+
save.saveFile(config, fileFormat, sbomResponse)
|
|
39
|
+
}
|
|
38
40
|
}
|
|
39
41
|
const filename = `${config.applicationId}-sbom-${fileFormat}.json`
|
|
40
42
|
if (fs.existsSync(filename)) {
|
|
@@ -42,7 +44,7 @@ async function auditSave(config, reportId) {
|
|
|
42
44
|
} else {
|
|
43
45
|
console.log(
|
|
44
46
|
chalk.yellow.bold(
|
|
45
|
-
`\
|
|
47
|
+
`\nUnable to save ${filename} Software Bill of Materials (SBOM)`
|
|
46
48
|
)
|
|
47
49
|
)
|
|
48
50
|
}
|
package/src/cliConstants.js
CHANGED
|
@@ -212,6 +212,7 @@ const scanOptionDefinitions = [
|
|
|
212
212
|
|
|
213
213
|
const authOptionDefinitions = [
|
|
214
214
|
...sharedConnectionOptionDefinitions,
|
|
215
|
+
...sharedCertOptionDefinitions,
|
|
215
216
|
{
|
|
216
217
|
name: 'help',
|
|
217
218
|
alias: 'h',
|
|
@@ -427,11 +428,11 @@ const mainUsageGuide = commandLineUsage([
|
|
|
427
428
|
header: i18n.__('constantsCommands'),
|
|
428
429
|
content: [
|
|
429
430
|
{ name: i18n.__('authName'), summary: i18n.__('helpAuthSummary') },
|
|
431
|
+
{ name: i18n.__('configName'), summary: i18n.__('helpConfigSummary') },
|
|
432
|
+
{ name: i18n.__('versionName'), summary: i18n.__('helpVersionSummary') },
|
|
433
|
+
{ name: i18n.__('auditName'), summary: i18n.__('helpAuditSummary') },
|
|
430
434
|
{ name: i18n.__('scanName'), summary: i18n.__('helpScanSummary') },
|
|
431
435
|
{ name: i18n.__('lambdaName'), summary: i18n.__('helpLambdaSummary') },
|
|
432
|
-
{ name: i18n.__('auditName'), summary: i18n.__('helpAuditSummary') },
|
|
433
|
-
{ name: i18n.__('versionName'), summary: i18n.__('helpVersionSummary') },
|
|
434
|
-
{ name: i18n.__('configName'), summary: i18n.__('helpConfigSummary') },
|
|
435
436
|
{ name: i18n.__('helpName'), summary: i18n.__('helpSummary') },
|
|
436
437
|
{ name: i18n.__('learnName'), summary: i18n.__('helpLearnSummary') }
|
|
437
438
|
]
|
|
@@ -4,6 +4,9 @@ const constants = require('../../cliConstants')
|
|
|
4
4
|
const { commonHelpLinks } = require('../../common/commonHelp')
|
|
5
5
|
|
|
6
6
|
const auditUsageGuide = commandLineUsage([
|
|
7
|
+
{
|
|
8
|
+
header: i18n.__('constantsHeader')
|
|
9
|
+
},
|
|
7
10
|
{
|
|
8
11
|
header: i18n.__('auditHeader'),
|
|
9
12
|
content: [i18n.__('auditHeaderMessage')]
|
|
@@ -48,7 +51,6 @@ const auditUsageGuide = commandLineUsage([
|
|
|
48
51
|
'code',
|
|
49
52
|
'maven-settings-path',
|
|
50
53
|
'language',
|
|
51
|
-
'experimental',
|
|
52
54
|
'app-groups',
|
|
53
55
|
'metadata',
|
|
54
56
|
'track',
|
|
@@ -10,11 +10,8 @@ const processAudit = async (contrastConf, argvMain) => {
|
|
|
10
10
|
process.exit(0)
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
'audit',
|
|
16
|
-
argvMain
|
|
17
|
-
)
|
|
13
|
+
let config = await auditConfig.getAuditConfig(contrastConf, 'audit', argvMain)
|
|
14
|
+
|
|
18
15
|
await scaController.processSca(config)
|
|
19
16
|
if (!config.fingerprint) {
|
|
20
17
|
postRunMessage('audit')
|
|
@@ -101,6 +101,11 @@ const authUsageGuide = commandLineUsage([
|
|
|
101
101
|
{
|
|
102
102
|
header: i18n.__('constantsAuthUsageHeader'),
|
|
103
103
|
content: [i18n.__('constantsAuthUsageContents')]
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
header: i18n.__('constantsAdvancedOptions'),
|
|
107
|
+
optionList: constants.commandLineDefinitions.authOptionDefinitions,
|
|
108
|
+
hide: ['organization-id', 'api-key', 'authorization', 'host']
|
|
104
109
|
}
|
|
105
110
|
])
|
|
106
111
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const { openLearnPage } = require('./learn')
|
|
2
2
|
|
|
3
3
|
async function processLearn() {
|
|
4
|
-
console.log('Opening
|
|
4
|
+
console.log('Opening Contrast’s Secure Code Learning Hub...')
|
|
5
5
|
console.log(
|
|
6
6
|
'If the page does not open you can open it directly via https://www.contrastsecurity.com/developer/learn'
|
|
7
7
|
)
|
package/src/common/HTTPClient.js
CHANGED
|
@@ -254,6 +254,13 @@ HTTPClient.prototype.scaServiceIngests = function scaServiceIngests(config) {
|
|
|
254
254
|
return requestUtils.sendRequest({ method: 'get', options })
|
|
255
255
|
}
|
|
256
256
|
|
|
257
|
+
HTTPClient.prototype.scaServiceHealth = function scaServiceIngests(config) {
|
|
258
|
+
const options = _.cloneDeep(this.requestOptions)
|
|
259
|
+
let url = createScaServiceHealthURL(config)
|
|
260
|
+
options.url = url
|
|
261
|
+
return requestUtils.sendRequest({ method: 'get', options })
|
|
262
|
+
}
|
|
263
|
+
|
|
257
264
|
HTTPClient.prototype.getReportById = function getReportById(config, reportId) {
|
|
258
265
|
const options = _.cloneDeep(this.requestOptions)
|
|
259
266
|
if (config.ignoreDev) {
|
|
@@ -474,6 +481,10 @@ function createScaServiceIngestsURL(config) {
|
|
|
474
481
|
return `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/applications/${config.applicationId}/libraries/ingests`
|
|
475
482
|
}
|
|
476
483
|
|
|
484
|
+
function createScaServiceHealthURL(config) {
|
|
485
|
+
return `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/health`
|
|
486
|
+
}
|
|
487
|
+
|
|
477
488
|
function createScaServiceIngestURL(config) {
|
|
478
489
|
let baseUrl = `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/applications/${config.applicationId}/libraries/ingests/tree`
|
|
479
490
|
baseUrl = config.track ? baseUrl.concat('?persist=true') : baseUrl
|
package/src/constants/lambda.js
CHANGED
|
@@ -66,6 +66,7 @@ const lambda = {
|
|
|
66
66
|
'Scanning a function of an inactive account is not supported',
|
|
67
67
|
not_supported_runtime:
|
|
68
68
|
'Scanning resource of runtime "{{runtime}}" is not supported.\nSupported runtimes: {{supportedRuntimes}}',
|
|
69
|
+
not_supported_lambda: 'This function cannot be scanned',
|
|
69
70
|
not_supported_onboard_account:
|
|
70
71
|
'Scanning a function of onboard account is not supported',
|
|
71
72
|
scan_lock:
|
package/src/constants/locales.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const { lambda } = require('./lambda')
|
|
2
2
|
const chalk = require('chalk')
|
|
3
|
+
const { APP_VERSION } = require('./constants')
|
|
3
4
|
|
|
4
5
|
const en_locales = () => {
|
|
5
6
|
return {
|
|
@@ -83,7 +84,7 @@ const en_locales = () => {
|
|
|
83
84
|
' FAIL - Results detected vulnerabilities over accepted severity level',
|
|
84
85
|
constantsSeverity:
|
|
85
86
|
'Use with "contrast scan --fail --severity high" or "contrast audit --fail --severity high". Set the severity level to detect vulnerabilities or dependencies. Severity levels are critical, high, medium, low or note.',
|
|
86
|
-
constantsHeader:
|
|
87
|
+
constantsHeader: `Contrast CLI @ v${APP_VERSION}`,
|
|
87
88
|
configHeader2: 'Config options',
|
|
88
89
|
clearHeader: '-c, --clear',
|
|
89
90
|
clearContent: 'Removes stored credentials',
|
|
@@ -160,13 +161,13 @@ const en_locales = () => {
|
|
|
160
161
|
scanErrorFileMessage:
|
|
161
162
|
'We only accept the following file types: \nJava - .jar, .war \nJavaScript - .js or .zip files',
|
|
162
163
|
helpAuthSummary:
|
|
163
|
-
'Authenticate Contrast using your Github or Google account',
|
|
164
|
+
'Authenticate Contrast using your Github or Google account OR include credentials if you are an existing licensed Contrast user.',
|
|
164
165
|
helpAuditSummary:
|
|
165
|
-
'Searches for a suitable file in the working directory to perform a security audit of dependencies and returns the results. [
|
|
166
|
+
'Searches for a suitable file in the working directory to perform a security audit of dependencies and returns the results. \n[audit --help for options] Java, .NET, Node, Ruby, Python, Go, PHP are supported. ',
|
|
166
167
|
helpScanSummary:
|
|
167
|
-
'Searches for a .jar, .war, .js, or .zip file in the working directory, uploads files for analysis, and returns the results. [
|
|
168
|
+
'Searches for a .jar, .war, .js, or .zip file in the working directory, uploads files for analysis, and returns the results. \n[scan --help for options] Java, .NET, .NET Core, JavaScript are supported. ',
|
|
168
169
|
helpLambdaSummary:
|
|
169
|
-
'Performs a static security scan on an AWS lambda function. lambda --help
|
|
170
|
+
'Performs a static security scan on an AWS lambda function. [lambda --help for options] AWS Lambda - Java & Python are supported. ',
|
|
170
171
|
helpVersionSummary: 'Displays version of Contrast CLI',
|
|
171
172
|
helpConfigSummary: 'Displays stored credentials',
|
|
172
173
|
helpSummary: 'Displays usage guide',
|
|
@@ -178,7 +179,7 @@ const en_locales = () => {
|
|
|
178
179
|
configName: 'config',
|
|
179
180
|
helpName: 'help',
|
|
180
181
|
learnName: 'learn',
|
|
181
|
-
helpLearnSummary: '
|
|
182
|
+
helpLearnSummary: 'Launches Contrast’s Secure Code Learning Hub.',
|
|
182
183
|
fingerprintName:
|
|
183
184
|
'assess repo to see how many languages it can detect. For use in pipeline only.',
|
|
184
185
|
depthOption:
|
|
@@ -202,7 +203,7 @@ const en_locales = () => {
|
|
|
202
203
|
chalk.bold('\ncontrast audit') +
|
|
203
204
|
' to find vulnerabilities in your open source dependencies.' +
|
|
204
205
|
'\nSupports Java, .NET, Node, Ruby, Python, Go and PHP.' +
|
|
205
|
-
'\nOur CLI runs native build tools to generate a complete dependency tree.' +
|
|
206
|
+
'\n\nOur CLI runs native build tools to generate a complete dependency tree.' +
|
|
206
207
|
'\nIf you are running on untrusted code, consider running in a sandbox.\n' +
|
|
207
208
|
chalk.bold('\ncontrast lambda') +
|
|
208
209
|
' to secure your AWS serverless functions. \nSupports Java and Python \n' +
|
|
@@ -216,7 +217,7 @@ const en_locales = () => {
|
|
|
216
217
|
searchingScanFileDirectory: 'Searching for file to scan from %s...',
|
|
217
218
|
searchingAuditFileDirectory:
|
|
218
219
|
'Searching for package manager files from %s...',
|
|
219
|
-
scanHeader:
|
|
220
|
+
scanHeader: `Contrast Scan CLI`,
|
|
220
221
|
authHeader: 'Auth',
|
|
221
222
|
lambdaHeader: 'Contrast Lambda CLI',
|
|
222
223
|
lambdaSummary:
|
|
@@ -257,7 +258,7 @@ const en_locales = () => {
|
|
|
257
258
|
'An error has occurred when trying to get the Project Id please check your internet connection or provide the Project Id manually',
|
|
258
259
|
internalServerErrorHeader: '500 error - Internal server error',
|
|
259
260
|
resourceLockedErrorHeader: '423 error - Resource is locked',
|
|
260
|
-
auditHeader: 'Contrast
|
|
261
|
+
auditHeader: 'Contrast Audit CLI',
|
|
261
262
|
auditHeaderMessage:
|
|
262
263
|
"Use 'contrast audit' to analyze a project’s dependencies for vulnerabilities.",
|
|
263
264
|
constantsAuditPrerequisitesContentSupportedLanguages:
|
|
@@ -329,18 +330,18 @@ const en_locales = () => {
|
|
|
329
330
|
commonHelpJoinDiscussionText:
|
|
330
331
|
' https://www.contrastsecurity.com/developer/community',
|
|
331
332
|
commonHelpLearnHeader:
|
|
332
|
-
chalk.hex('#ffe599')('\
|
|
333
|
+
chalk.hex('#ffe599')('\r Want to UP your game?') +
|
|
333
334
|
" type 'contrast learn'",
|
|
334
|
-
commonHelpLearnText: `\n
|
|
335
|
+
commonHelpLearnText: `\n💰 Advance your security knowledge and become an ${chalk.hex(
|
|
335
336
|
'#ffd966'
|
|
336
337
|
)('All-star coder')} ⭐ with ${chalk.bold(
|
|
337
338
|
'Contrast Secure Code Learning Hub.'
|
|
338
339
|
)} 😺`,
|
|
339
340
|
authCommand: {
|
|
340
341
|
credentialsAccepted: {
|
|
341
|
-
title: 'Credentials
|
|
342
|
-
body: '
|
|
343
|
-
extra: '
|
|
342
|
+
title: '✔ Credentials successfully saved',
|
|
343
|
+
body: `\n${chalk.bold('Contrast CLI')}`,
|
|
344
|
+
extra: 'Scan, secure and ship your code in minutes.'
|
|
344
345
|
},
|
|
345
346
|
credentialsMissing: {
|
|
346
347
|
title: 'Credentials missing',
|
package/src/index.ts
CHANGED
|
@@ -16,7 +16,6 @@ import {
|
|
|
16
16
|
} from './common/versionChecker'
|
|
17
17
|
import { findCommandOnError } from './common/errorHandling'
|
|
18
18
|
import { sendTelemetryConfigAsConfObj } from './telemetry/telemetry'
|
|
19
|
-
import { openLearnPage } from './commands/learn/learn'
|
|
20
19
|
import { processLearn } from './commands/learn/processLearn'
|
|
21
20
|
const {
|
|
22
21
|
commandLineDefinitions: { mainUsageGuide, mainDefinition }
|
package/src/lambda/help.ts
CHANGED
|
@@ -14,12 +14,22 @@ import { ApiParams, LambdaOptions } from './lambda'
|
|
|
14
14
|
import { log, prettyPrintJson } from './logUtils'
|
|
15
15
|
import { CliError } from './cliError'
|
|
16
16
|
import { ERRORS } from './constants'
|
|
17
|
+
import { sleep } from '../utils/requestUtils'
|
|
17
18
|
|
|
18
|
-
const
|
|
19
|
+
const MAX_RETRIES = 2
|
|
20
|
+
|
|
21
|
+
const sendScanPostRequest: (
|
|
19
22
|
config: any,
|
|
20
23
|
params: ApiParams,
|
|
21
24
|
functionsEvent: unknown,
|
|
22
|
-
showProgress
|
|
25
|
+
showProgress?: boolean,
|
|
26
|
+
retryNumber?: number
|
|
27
|
+
) => any = async (
|
|
28
|
+
config,
|
|
29
|
+
params,
|
|
30
|
+
functionsEvent,
|
|
31
|
+
showProgress = false,
|
|
32
|
+
retryNumber = 0
|
|
23
33
|
) => {
|
|
24
34
|
const client = getHttpClient(config)
|
|
25
35
|
|
|
@@ -50,6 +60,21 @@ const sendScanPostRequest = async (
|
|
|
50
60
|
})
|
|
51
61
|
errorCode = false
|
|
52
62
|
break
|
|
63
|
+
case 'not_supported_lambda':
|
|
64
|
+
description = i18n.__(errorCode)
|
|
65
|
+
errorCode = false
|
|
66
|
+
break
|
|
67
|
+
default:
|
|
68
|
+
if (retryNumber < MAX_RETRIES) {
|
|
69
|
+
await sleep(3 * 1000)
|
|
70
|
+
return sendScanPostRequest(
|
|
71
|
+
config,
|
|
72
|
+
params,
|
|
73
|
+
functionsEvent,
|
|
74
|
+
showProgress,
|
|
75
|
+
retryNumber + 1
|
|
76
|
+
)
|
|
77
|
+
}
|
|
53
78
|
}
|
|
54
79
|
|
|
55
80
|
throw new CliError(ERRORS.FAILED_TO_START_SCAN, {
|
package/src/sbom/generateSbom.ts
CHANGED
|
@@ -7,8 +7,15 @@ export const generateSbom = (config: any, type: string) => {
|
|
|
7
7
|
.then((res: { statusCode: number; body: any }) => {
|
|
8
8
|
if (res.statusCode === 200) {
|
|
9
9
|
return res.body
|
|
10
|
+
} else if (res.statusCode === 403) {
|
|
11
|
+
console.log('\nUnable to retrieve Software Bill of Materials (SBOM)')
|
|
12
|
+
console.log(
|
|
13
|
+
`Please ensure OSS is enabled for your organization - org-id ${config.organizationId} and app ${config.applicationId}`
|
|
14
|
+
)
|
|
15
|
+
return undefined
|
|
10
16
|
} else {
|
|
11
17
|
console.log('Unable to retrieve Software Bill of Materials (SBOM)')
|
|
18
|
+
return undefined
|
|
12
19
|
}
|
|
13
20
|
})
|
|
14
21
|
.catch((err: any) => {
|
|
@@ -29,6 +36,7 @@ export const generateSCASbom = (
|
|
|
29
36
|
return res.body
|
|
30
37
|
} else {
|
|
31
38
|
console.log('Unable to retrieve Software Bill of Materials (SBOM)')
|
|
39
|
+
return undefined
|
|
32
40
|
}
|
|
33
41
|
})
|
|
34
42
|
.catch((err: any) => {
|
|
@@ -217,9 +217,9 @@ function getIssueRow(cveArray) {
|
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
function getAdviceRow(advice) {
|
|
220
|
-
const latestOrClosest = advice.
|
|
221
|
-
? advice.
|
|
222
|
-
: advice.
|
|
220
|
+
const latestOrClosest = advice.closestStableVersion
|
|
221
|
+
? advice.closestStableVersion
|
|
222
|
+
: advice.latestStableVersion
|
|
223
223
|
const displayAdvice = latestOrClosest
|
|
224
224
|
? `Change to version ${chalk.bold(latestOrClosest)}`
|
|
225
225
|
: 'No recommendation is available according to our data. Upgrade to the latest stable is the best advice we can give.'
|
|
@@ -3,13 +3,11 @@ const { APP_VERSION } = require('../../constants/constants')
|
|
|
3
3
|
|
|
4
4
|
const commonSendSnapShot = async (analysis, config) => {
|
|
5
5
|
let requestBody = {}
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
:
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
snapshot: analysis
|
|
12
|
-
})
|
|
6
|
+
requestBody = {
|
|
7
|
+
appID: config.applicationId,
|
|
8
|
+
cliVersion: APP_VERSION,
|
|
9
|
+
snapshot: analysis
|
|
10
|
+
}
|
|
13
11
|
|
|
14
12
|
const client = commonApi.getHttpClient(config)
|
|
15
13
|
return client
|
|
@@ -18,6 +16,13 @@ const commonSendSnapShot = async (analysis, config) => {
|
|
|
18
16
|
if (res.statusCode === 201) {
|
|
19
17
|
return res.body
|
|
20
18
|
} else {
|
|
19
|
+
if (res.statusCode === 403) {
|
|
20
|
+
throw new Error(
|
|
21
|
+
`🛑 Contrast audit failed \nPlease check you have the right permissions and the application ${
|
|
22
|
+
config.applicationName ? config.applicationName : ''
|
|
23
|
+
} has not been archived.`.replace(/ +(?= )/g, '')
|
|
24
|
+
)
|
|
25
|
+
}
|
|
21
26
|
throw new Error(res.statusCode + ` error processing dependencies`)
|
|
22
27
|
}
|
|
23
28
|
})
|
|
@@ -26,19 +31,6 @@ const commonSendSnapShot = async (analysis, config) => {
|
|
|
26
31
|
})
|
|
27
32
|
}
|
|
28
33
|
|
|
29
|
-
const sendToSCAServices = (config, analysis) => {
|
|
30
|
-
return {
|
|
31
|
-
applicationId: config.applicationId,
|
|
32
|
-
dependencyTree: analysis,
|
|
33
|
-
organizationId: config.organizationId,
|
|
34
|
-
language: config.language,
|
|
35
|
-
tool: {
|
|
36
|
-
name: 'Contrast Codesec',
|
|
37
|
-
version: APP_VERSION
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
34
|
module.exports = {
|
|
43
35
|
commonSendSnapShot
|
|
44
36
|
}
|
|
@@ -10,12 +10,7 @@ const goAnalysis = config => {
|
|
|
10
10
|
const rawGoDependencies = goReadDepFile.getGoDependencies(config)
|
|
11
11
|
const parsedGoDependencies =
|
|
12
12
|
goParseDeps.parseGoDependencies(rawGoDependencies)
|
|
13
|
-
|
|
14
|
-
if (config.experimental) {
|
|
15
|
-
return parseDependenciesForSCAServices(parsedGoDependencies)
|
|
16
|
-
} else {
|
|
17
|
-
return createGoTSMessage(parsedGoDependencies)
|
|
18
|
-
}
|
|
13
|
+
return createGoTSMessage(parsedGoDependencies)
|
|
19
14
|
} catch (e) {
|
|
20
15
|
console.log(e.message.toString())
|
|
21
16
|
}
|