@contrast/contrast 1.0.10 → 1.0.13
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 +1 -1
- package/dist/audit/{languageAnalysisEngine/report → report}/commonReportingFunctions.js +56 -35
- package/dist/audit/report/models/reportGuidanceModel.js +6 -0
- package/dist/audit/{languageAnalysisEngine/report → report}/models/reportLibraryModel.js +0 -0
- package/dist/audit/{languageAnalysisEngine/report → report}/models/reportListModel.js +0 -0
- package/dist/audit/{languageAnalysisEngine/report → report}/models/reportOutputModel.js +1 -2
- package/dist/audit/{languageAnalysisEngine/report → report}/models/reportSeverityModel.js +0 -0
- package/dist/audit/{languageAnalysisEngine/report → report}/models/severityCountModel.js +1 -0
- package/dist/audit/{languageAnalysisEngine/report → report}/reportingFeature.js +12 -8
- package/dist/audit/{languageAnalysisEngine/report → report}/utils/reportUtils.js +3 -4
- package/dist/commands/audit/auditConfig.js +3 -3
- package/dist/commands/audit/help.js +3 -1
- package/dist/commands/audit/processAudit.js +14 -2
- package/dist/commands/auth/auth.js +1 -1
- package/dist/commands/config/config.js +2 -2
- package/dist/commands/scan/processScan.js +20 -4
- package/dist/commands/scan/sca/scaAnalysis.js +15 -5
- package/dist/common/HTTPClient.js +39 -2
- package/dist/common/commonHelp.js +19 -0
- package/dist/common/fail.js +70 -0
- package/dist/common/versionChecker.js +14 -6
- package/dist/constants/constants.js +2 -2
- package/dist/constants/locales.js +15 -5
- package/dist/constants.js +42 -5
- package/dist/index.js +6 -3
- package/dist/lambda/help.js +2 -3
- package/dist/lambda/lambda.js +7 -0
- package/dist/scaAnalysis/common/scaParserForGoAndJava.js +32 -0
- package/dist/scaAnalysis/common/scaServicesUpload.js +52 -0
- package/dist/scaAnalysis/common/treeUpload.js +20 -5
- package/dist/scaAnalysis/dotnet/analysis.js +15 -3
- package/dist/scaAnalysis/go/goAnalysis.js +8 -2
- package/dist/scaAnalysis/java/analysis.js +10 -6
- package/dist/scaAnalysis/java/index.js +7 -1
- package/dist/scaAnalysis/java/javaBuildDepsParser.js +19 -3
- package/dist/scaAnalysis/javascript/index.js +4 -0
- package/dist/scaAnalysis/javascript/scaServiceParser.js +109 -0
- package/dist/scaAnalysis/php/analysis.js +1 -1
- package/dist/scaAnalysis/php/index.js +12 -6
- package/dist/scaAnalysis/php/phpNewServicesMapper.js +62 -0
- package/dist/scaAnalysis/python/analysis.js +43 -5
- package/dist/scaAnalysis/python/index.js +7 -2
- package/dist/scaAnalysis/ruby/analysis.js +116 -9
- package/dist/scaAnalysis/ruby/index.js +6 -1
- package/dist/scan/formatScanOutput.js +6 -5
- package/dist/scan/help.js +2 -3
- package/dist/scan/populateProjectIdAndProjectName.js +5 -0
- package/dist/scan/scan.js +4 -0
- package/dist/scan/scanConfig.js +4 -4
- package/dist/scan/scanResults.js +46 -3
- package/dist/telemetry/telemetry.js +137 -0
- package/dist/{audit/languageAnalysisEngine/util → utils}/capabilities.js +0 -0
- package/dist/{audit/languageAnalysisEngine/util → utils}/generalAPI.js +14 -5
- package/dist/utils/getConfig.js +2 -4
- package/dist/utils/parsedCLIOptions.js +3 -1
- package/dist/utils/requestUtils.js +7 -1
- package/package.json +4 -2
- package/src/audit/{languageAnalysisEngine/report → report}/commonReportingFunctions.ts +80 -44
- package/src/audit/report/models/reportGuidanceModel.ts +5 -0
- package/src/audit/{languageAnalysisEngine/report → report}/models/reportLibraryModel.ts +0 -0
- package/src/audit/{languageAnalysisEngine/report → report}/models/reportListModel.ts +0 -0
- package/src/audit/{languageAnalysisEngine/report → report}/models/reportOutputModel.ts +1 -7
- package/src/audit/{languageAnalysisEngine/report → report}/models/reportSeverityModel.ts +0 -0
- package/src/audit/{languageAnalysisEngine/report → report}/models/severityCountModel.ts +2 -0
- package/src/audit/{languageAnalysisEngine/report → report}/reportingFeature.ts +16 -9
- package/src/audit/{languageAnalysisEngine/report → report}/utils/reportUtils.ts +4 -4
- package/src/commands/audit/auditConfig.ts +10 -3
- package/src/commands/audit/help.ts +3 -1
- package/src/commands/audit/processAudit.ts +24 -2
- package/src/commands/auth/auth.js +3 -1
- package/src/commands/config/config.js +4 -2
- package/src/commands/scan/processScan.js +32 -4
- package/src/commands/scan/sca/scaAnalysis.js +23 -5
- package/src/common/HTTPClient.js +59 -2
- package/src/common/commonHelp.ts +13 -0
- package/src/common/fail.js +79 -0
- package/src/common/versionChecker.ts +18 -8
- package/src/constants/constants.js +2 -2
- package/src/constants/locales.js +19 -7
- package/src/constants.js +46 -6
- package/src/index.ts +18 -4
- package/src/lambda/help.ts +2 -3
- package/src/lambda/lambda.ts +12 -0
- package/src/scaAnalysis/common/scaParserForGoAndJava.js +41 -0
- package/src/scaAnalysis/common/scaServicesUpload.js +54 -0
- package/src/scaAnalysis/common/treeUpload.js +21 -5
- package/src/scaAnalysis/dotnet/analysis.js +21 -3
- package/src/scaAnalysis/go/goAnalysis.js +9 -2
- package/src/scaAnalysis/java/analysis.js +11 -6
- package/src/scaAnalysis/java/index.js +9 -1
- package/src/scaAnalysis/java/javaBuildDepsParser.js +25 -6
- package/src/scaAnalysis/javascript/index.js +4 -0
- package/src/scaAnalysis/javascript/scaServiceParser.js +145 -0
- package/src/scaAnalysis/php/analysis.js +1 -1
- package/src/scaAnalysis/php/index.js +12 -6
- package/src/scaAnalysis/php/phpNewServicesMapper.js +77 -0
- package/src/scaAnalysis/python/analysis.js +49 -5
- package/src/scaAnalysis/python/index.js +7 -2
- package/src/scaAnalysis/ruby/analysis.js +149 -9
- package/src/scaAnalysis/ruby/index.js +6 -1
- package/src/scan/formatScanOutput.ts +7 -5
- package/src/scan/help.js +2 -3
- package/src/scan/populateProjectIdAndProjectName.js +5 -1
- package/src/scan/scan.ts +4 -0
- package/src/scan/scanConfig.js +6 -4
- package/src/scan/scanResults.js +52 -3
- package/src/telemetry/telemetry.ts +154 -0
- package/src/{audit/languageAnalysisEngine/util → utils}/capabilities.js +0 -0
- package/src/{audit/languageAnalysisEngine/util → utils}/generalAPI.js +16 -6
- package/src/utils/getConfig.ts +2 -11
- package/src/utils/parsedCLIOptions.js +14 -1
- package/src/utils/requestUtils.js +8 -1
|
@@ -1,18 +1,40 @@
|
|
|
1
1
|
import { getAuditConfig } from './auditConfig'
|
|
2
2
|
import { auditUsageGuide } from './help'
|
|
3
3
|
import { processSca } from '../scan/sca/scaAnalysis'
|
|
4
|
+
import { sendTelemetryConfigAsObject } from '../../telemetry/telemetry'
|
|
5
|
+
import { ContrastConf } from '../../utils/getConfig'
|
|
6
|
+
import chalk from 'chalk'
|
|
4
7
|
|
|
5
8
|
export type parameterInput = string[]
|
|
6
9
|
|
|
7
|
-
export const processAudit = async (
|
|
10
|
+
export const processAudit = async (
|
|
11
|
+
contrastConf: ContrastConf,
|
|
12
|
+
argv: parameterInput
|
|
13
|
+
) => {
|
|
8
14
|
if (argv.indexOf('--help') != -1) {
|
|
9
15
|
printHelpMessage()
|
|
10
16
|
process.exit(0)
|
|
11
17
|
}
|
|
12
|
-
|
|
18
|
+
|
|
19
|
+
const config = await getAuditConfig(contrastConf, 'audit', argv)
|
|
13
20
|
await processSca(config)
|
|
21
|
+
postRunMessage()
|
|
22
|
+
await sendTelemetryConfigAsObject(
|
|
23
|
+
config,
|
|
24
|
+
'audit',
|
|
25
|
+
argv,
|
|
26
|
+
'SUCCESS',
|
|
27
|
+
// @ts-ignore
|
|
28
|
+
config.language
|
|
29
|
+
)
|
|
14
30
|
}
|
|
15
31
|
|
|
16
32
|
const printHelpMessage = () => {
|
|
17
33
|
console.log(auditUsageGuide)
|
|
18
34
|
}
|
|
35
|
+
|
|
36
|
+
const postRunMessage = () => {
|
|
37
|
+
console.log('\n' + chalk.underline.bold('Other Codesec Features:'))
|
|
38
|
+
console.log("'contrast scan' to run CodeSec’s industry leading SAST scanner")
|
|
39
|
+
console.log("'contrast lambda' to secure your AWS serverless functions\n")
|
|
40
|
+
}
|
|
@@ -16,7 +16,9 @@ const constants = require('../../constants')
|
|
|
16
16
|
const commandLineUsage = require('command-line-usage')
|
|
17
17
|
|
|
18
18
|
const processAuth = async (argv, config) => {
|
|
19
|
-
let authParams = parsedCLIOptions.getCommandLineArgsCustom(
|
|
19
|
+
let authParams = await parsedCLIOptions.getCommandLineArgsCustom(
|
|
20
|
+
config,
|
|
21
|
+
'auth',
|
|
20
22
|
argv,
|
|
21
23
|
constants.commandLineDefinitions.authOptionDefinitions
|
|
22
24
|
)
|
|
@@ -3,9 +3,11 @@ const constants = require('../../constants')
|
|
|
3
3
|
const commandLineUsage = require('command-line-usage')
|
|
4
4
|
const i18n = require('i18n')
|
|
5
5
|
|
|
6
|
-
const processConfig = (argv, config) => {
|
|
6
|
+
const processConfig = async (argv, config) => {
|
|
7
7
|
try {
|
|
8
|
-
let configParams = parsedCLIOptions.getCommandLineArgsCustom(
|
|
8
|
+
let configParams = await parsedCLIOptions.getCommandLineArgsCustom(
|
|
9
|
+
config,
|
|
10
|
+
'config',
|
|
9
11
|
argv,
|
|
10
12
|
constants.commandLineDefinitions.configOptionDefinitions
|
|
11
13
|
)
|
|
@@ -4,23 +4,51 @@ const { saveScanFile } = require('../../utils/saveFile')
|
|
|
4
4
|
const { ScanResultsModel } = require('../../scan/models/scanResultsModel')
|
|
5
5
|
const { formatScanOutput } = require('../../scan/formatScanOutput')
|
|
6
6
|
const { processSca } = require('./sca/scaAnalysis')
|
|
7
|
+
const common = require('../../common/fail')
|
|
8
|
+
const { sendTelemetryConfigAsObject } = require('../../telemetry/telemetry')
|
|
9
|
+
const chalk = require('chalk')
|
|
10
|
+
const generalAPI = require('../../utils/generalAPI')
|
|
11
|
+
|
|
12
|
+
const processScan = async (contrastConf, argv) => {
|
|
13
|
+
let config = await scanConfig.getScanConfig(contrastConf, 'scan', argv)
|
|
14
|
+
let output = undefined
|
|
15
|
+
config.mode = await generalAPI.getMode(config)
|
|
7
16
|
|
|
8
|
-
const processScan = async argvMain => {
|
|
9
|
-
let config = scanConfig.getScanConfig(argvMain)
|
|
10
17
|
//try SCA analysis first
|
|
11
18
|
if (config.experimental) {
|
|
12
|
-
await processSca(config)
|
|
19
|
+
await processSca(config, argv)
|
|
13
20
|
}
|
|
14
21
|
|
|
15
22
|
let scanResults = new ScanResultsModel(await startScan(config))
|
|
23
|
+
await sendTelemetryConfigAsObject(
|
|
24
|
+
config,
|
|
25
|
+
'scan',
|
|
26
|
+
argv,
|
|
27
|
+
'SUCCESS',
|
|
28
|
+
scanResults.scanDetail.language
|
|
29
|
+
)
|
|
16
30
|
|
|
17
31
|
if (scanResults.scanResultsInstances !== undefined) {
|
|
18
|
-
formatScanOutput(scanResults)
|
|
32
|
+
output = formatScanOutput(scanResults)
|
|
19
33
|
}
|
|
20
34
|
|
|
21
35
|
if (config.save !== undefined) {
|
|
22
36
|
await saveScanFile(config, scanResults)
|
|
23
37
|
}
|
|
38
|
+
|
|
39
|
+
if (config.fail) {
|
|
40
|
+
common.processFail(config, output)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
postRunMessage()
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const postRunMessage = () => {
|
|
47
|
+
console.log('\n' + chalk.underline.bold('Other Codesec Features:'))
|
|
48
|
+
console.log(
|
|
49
|
+
"'contrast audit' to find vulnerabilities in your open source dependencies"
|
|
50
|
+
)
|
|
51
|
+
console.log("'contrast lambda' to secure your AWS serverless functions\n")
|
|
24
52
|
}
|
|
25
53
|
|
|
26
54
|
module.exports = {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const autoDetection = require('../../../scan/autoDetection')
|
|
2
2
|
const javaAnalysis = require('../../../scaAnalysis/java')
|
|
3
3
|
const treeUpload = require('../../../scaAnalysis/common/treeUpload')
|
|
4
|
+
const scaUpload = require('../../../scaAnalysis/common/scaServicesUpload')
|
|
4
5
|
const auditController = require('../../audit/auditController')
|
|
5
6
|
const {
|
|
6
7
|
supportedLanguages: { JAVA, GO, PYTHON, RUBY, JAVASCRIPT, NODE, PHP, DOTNET }
|
|
@@ -21,19 +22,29 @@ const {
|
|
|
21
22
|
const i18n = require('i18n')
|
|
22
23
|
const {
|
|
23
24
|
vulnerabilityReportV2
|
|
24
|
-
} = require('../../../audit/
|
|
25
|
+
} = require('../../../audit/report/reportingFeature')
|
|
25
26
|
const auditSave = require('../../../audit/save')
|
|
26
27
|
const { dotNetAnalysis } = require('../../../scaAnalysis/dotnet')
|
|
28
|
+
const { auditUsageGuide } = require('../../audit/help')
|
|
27
29
|
const rootFile = require('../../../audit/languageAnalysisEngine/getProjectRootFilenames')
|
|
28
30
|
const path = require('path')
|
|
31
|
+
const generalAPI = require('../../../utils/generalAPI')
|
|
32
|
+
|
|
29
33
|
const processSca = async config => {
|
|
34
|
+
config.mode = await generalAPI.getMode(config)
|
|
35
|
+
|
|
30
36
|
const startTime = performance.now()
|
|
31
37
|
let filesFound
|
|
32
38
|
|
|
39
|
+
if (config.help) {
|
|
40
|
+
console.log(auditUsageGuide)
|
|
41
|
+
process.exit(0)
|
|
42
|
+
}
|
|
43
|
+
|
|
33
44
|
const projectStats = await rootFile.getProjectStats(config.file)
|
|
34
45
|
let pathWithFile = projectStats.isFile()
|
|
35
46
|
|
|
36
|
-
|
|
47
|
+
config.fileName = config.file
|
|
37
48
|
config.file = pathWithFile
|
|
38
49
|
? rootFile.getDirectoryFromPathGiven(config.file).concat('/')
|
|
39
50
|
: config.file
|
|
@@ -42,7 +53,7 @@ const processSca = async config => {
|
|
|
42
53
|
|
|
43
54
|
if (filesFound.length > 1 && pathWithFile) {
|
|
44
55
|
filesFound = filesFound.filter(i =>
|
|
45
|
-
Object.values(i)[0].includes(path.basename(fileName))
|
|
56
|
+
Object.values(i)[0].includes(path.basename(config.fileName))
|
|
46
57
|
)
|
|
47
58
|
}
|
|
48
59
|
|
|
@@ -71,7 +82,7 @@ const processSca = async config => {
|
|
|
71
82
|
messageToSend = rubyAnalysis(config, filesFound[0])
|
|
72
83
|
config.language = RUBY
|
|
73
84
|
break
|
|
74
|
-
case
|
|
85
|
+
case PHP:
|
|
75
86
|
messageToSend = phpAnalysis.phpAnalysis(config, filesFound[0])
|
|
76
87
|
config.language = PHP
|
|
77
88
|
break
|
|
@@ -93,6 +104,10 @@ const processSca = async config => {
|
|
|
93
104
|
config.applicationId = await auditController.dealWithNoAppId(config)
|
|
94
105
|
}
|
|
95
106
|
|
|
107
|
+
// if (config.experimental) {
|
|
108
|
+
// await scaUpload.scaTreeUpload(messageToSend, config)
|
|
109
|
+
// } else
|
|
110
|
+
// {
|
|
96
111
|
console.log('') //empty log for space before spinner
|
|
97
112
|
//send message to TS
|
|
98
113
|
const reportSpinner = returnOra(i18n.__('auditSCAAnalysisBegins'))
|
|
@@ -120,6 +135,7 @@ const processSca = async config => {
|
|
|
120
135
|
console.log(
|
|
121
136
|
`----- completed in ${(scanDurationMs / 1000).toFixed(2)}s -----`
|
|
122
137
|
)
|
|
138
|
+
// }
|
|
123
139
|
} else {
|
|
124
140
|
if (filesFound.length === 0) {
|
|
125
141
|
console.log(i18n.__('languageAnalysisNoLanguage'))
|
|
@@ -127,7 +143,9 @@ const processSca = async config => {
|
|
|
127
143
|
throw new Error()
|
|
128
144
|
} else {
|
|
129
145
|
throw new Error(
|
|
130
|
-
|
|
146
|
+
`multiple language files detected \n` +
|
|
147
|
+
JSON.stringify(filesFound) +
|
|
148
|
+
`\nplease use --file to audit one language only. Example: contrast audit --file package-lock.json`
|
|
131
149
|
)
|
|
132
150
|
}
|
|
133
151
|
}
|
package/src/common/HTTPClient.js
CHANGED
|
@@ -171,9 +171,9 @@ HTTPClient.prototype.getScanProjectById = function getScanProjectById(config) {
|
|
|
171
171
|
return requestUtils.sendRequest({ method: 'get', options })
|
|
172
172
|
}
|
|
173
173
|
|
|
174
|
-
HTTPClient.prototype.getGlobalProperties = function getGlobalProperties() {
|
|
174
|
+
HTTPClient.prototype.getGlobalProperties = function getGlobalProperties(host) {
|
|
175
175
|
const options = _.cloneDeep(this.requestOptions)
|
|
176
|
-
let url = createGlobalPropertiesUrl(
|
|
176
|
+
let url = createGlobalPropertiesUrl(host)
|
|
177
177
|
options.url = url
|
|
178
178
|
return requestUtils.sendRequest({ method: 'get', options })
|
|
179
179
|
}
|
|
@@ -212,9 +212,40 @@ HTTPClient.prototype.sendSnapshot = function sendSnapshot(requestBody, config) {
|
|
|
212
212
|
let url = createSnapshotURL(config)
|
|
213
213
|
options.url = url
|
|
214
214
|
options.body = requestBody
|
|
215
|
+
|
|
215
216
|
return requestUtils.sendRequest({ method: 'post', options })
|
|
216
217
|
}
|
|
217
218
|
|
|
219
|
+
HTTPClient.prototype.scaServiceIngest = function scaServiceIngest(
|
|
220
|
+
requestBody,
|
|
221
|
+
config
|
|
222
|
+
) {
|
|
223
|
+
const options = _.cloneDeep(this.requestOptions)
|
|
224
|
+
let url = createScaServiceIngestURL(config)
|
|
225
|
+
options.url = url
|
|
226
|
+
options.body = requestBody
|
|
227
|
+
return requestUtils.sendRequest({ method: 'post', options })
|
|
228
|
+
}
|
|
229
|
+
HTTPClient.prototype.scaServiceReport = function scaServiceReport(
|
|
230
|
+
config,
|
|
231
|
+
reportId
|
|
232
|
+
) {
|
|
233
|
+
const options = _.cloneDeep(this.requestOptions)
|
|
234
|
+
let url = createScaServiceReportURL(config, reportId)
|
|
235
|
+
options.url = url
|
|
236
|
+
return requestUtils.sendRequest({ method: 'get', options })
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
HTTPClient.prototype.scaServiceReportStatus = function scaServiceReport(
|
|
240
|
+
config,
|
|
241
|
+
reportId
|
|
242
|
+
) {
|
|
243
|
+
const options = _.cloneDeep(this.requestOptions)
|
|
244
|
+
let url = createScaServiceReportStatusURL(config, reportId)
|
|
245
|
+
options.url = url
|
|
246
|
+
return requestUtils.sendRequest({ method: 'get', options })
|
|
247
|
+
}
|
|
248
|
+
|
|
218
249
|
HTTPClient.prototype.getReportById = function getReportById(config, reportId) {
|
|
219
250
|
const options = _.cloneDeep(this.requestOptions)
|
|
220
251
|
if (config.ignoreDev) {
|
|
@@ -346,6 +377,16 @@ HTTPClient.prototype.getLatestVersion = function getLatestVersion() {
|
|
|
346
377
|
return requestUtils.sendRequest({ method: 'get', options })
|
|
347
378
|
}
|
|
348
379
|
|
|
380
|
+
HTTPClient.prototype.postTelemetry = function postTelemetry(
|
|
381
|
+
config,
|
|
382
|
+
requestBody
|
|
383
|
+
) {
|
|
384
|
+
const options = _.cloneDeep(this.requestOptions)
|
|
385
|
+
options.url = createTelemetryEventUrl(config)
|
|
386
|
+
options.body = requestBody
|
|
387
|
+
return requestUtils.sendRequest({ method: 'post', options })
|
|
388
|
+
}
|
|
389
|
+
|
|
349
390
|
// analytics
|
|
350
391
|
|
|
351
392
|
HTTPClient.prototype.postAnalyticsFunction = function (config, provider, body) {
|
|
@@ -405,6 +446,18 @@ function createSnapshotURL(config) {
|
|
|
405
446
|
return `${config.host}/Contrast/api/ng/sca/organizations/${config.organizationId}/applications/${config.applicationId}/snapshots`
|
|
406
447
|
}
|
|
407
448
|
|
|
449
|
+
function createScaServiceReportURL(config, reportId) {
|
|
450
|
+
return ``
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
function createScaServiceReportStatusURL(config, reportId) {
|
|
454
|
+
return ``
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
function createScaServiceIngestURL(config) {
|
|
458
|
+
return ``
|
|
459
|
+
}
|
|
460
|
+
|
|
408
461
|
const createAppCreateURL = config => {
|
|
409
462
|
return `${config.host}/Contrast/api/ng/sca/organizations/${config.organizationId}/applications/create`
|
|
410
463
|
}
|
|
@@ -439,6 +492,10 @@ function createSbomUrl(config, type) {
|
|
|
439
492
|
return `${config.host}/Contrast/api/ng/${config.organizationId}/applications/${config.applicationId}/libraries/sbom/${type}`
|
|
440
493
|
}
|
|
441
494
|
|
|
495
|
+
function createTelemetryEventUrl(config) {
|
|
496
|
+
return `${config.host}/Contrast/api/sast/organizations/${config.organizationId}/cli`
|
|
497
|
+
}
|
|
498
|
+
|
|
442
499
|
module.exports = HTTPClient
|
|
443
500
|
module.exports.pollForAuthUrl = pollForAuthUrl
|
|
444
501
|
module.exports.getServerlessHost = getServerlessHost
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import i18n from 'i18n'
|
|
2
|
+
|
|
3
|
+
export function commonHelpLinks() {
|
|
4
|
+
return {
|
|
5
|
+
header: i18n.__('commonHelpHeader'),
|
|
6
|
+
content: [
|
|
7
|
+
i18n.__('commonHelpCheckOutHeader') + i18n.__('commonHelpCheckOutText'),
|
|
8
|
+
i18n.__('commonHelpLearnMoreHeader') + i18n.__('commonHelpLearnMoreText'),
|
|
9
|
+
i18n.__('commonHelpJoinDiscussionHeader') +
|
|
10
|
+
i18n.__('commonHelpJoinDiscussionText')
|
|
11
|
+
]
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
const i18n = require('i18n')
|
|
2
|
+
|
|
3
|
+
const processFail = (config, reportResults) => {
|
|
4
|
+
if (config.severity !== undefined) {
|
|
5
|
+
if (
|
|
6
|
+
reportResults[config.severity] !== undefined &&
|
|
7
|
+
isSeverityViolation(config.severity, reportResults)
|
|
8
|
+
) {
|
|
9
|
+
failPipeline('failSeverityOptionErrorMessage')
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (config.severity === undefined && reportResults.total > 0) {
|
|
14
|
+
failPipeline('failThresholdOptionErrorMessage')
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const isSeverityViolation = (severity, reportResults) => {
|
|
19
|
+
let count = 0
|
|
20
|
+
switch (severity) {
|
|
21
|
+
case 'critical':
|
|
22
|
+
count += reportResults.critical
|
|
23
|
+
break
|
|
24
|
+
case 'high':
|
|
25
|
+
count += reportResults.high + reportResults.critical
|
|
26
|
+
break
|
|
27
|
+
case 'medium':
|
|
28
|
+
count +=
|
|
29
|
+
reportResults.medium + reportResults.high + reportResults.critical
|
|
30
|
+
break
|
|
31
|
+
case 'low':
|
|
32
|
+
count +=
|
|
33
|
+
reportResults.high +
|
|
34
|
+
reportResults.critical +
|
|
35
|
+
reportResults.medium +
|
|
36
|
+
reportResults.low
|
|
37
|
+
break
|
|
38
|
+
case 'note':
|
|
39
|
+
if (reportResults.note == reportResults.total) {
|
|
40
|
+
count = 0
|
|
41
|
+
} else {
|
|
42
|
+
count = reportResults.total
|
|
43
|
+
}
|
|
44
|
+
break
|
|
45
|
+
default:
|
|
46
|
+
count = 0
|
|
47
|
+
}
|
|
48
|
+
return count > 0
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const failPipeline = (message = '') => {
|
|
52
|
+
console.log(
|
|
53
|
+
'\n ******************************** ' +
|
|
54
|
+
i18n.__('snapshotFailureHeader') +
|
|
55
|
+
' *********************************\n' +
|
|
56
|
+
i18n.__(message)
|
|
57
|
+
)
|
|
58
|
+
process.exit(2)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const parseSeverity = severity => {
|
|
62
|
+
const severities = ['NOTE', 'LOW', 'MEDIUM', 'HIGH', 'CRITICAL']
|
|
63
|
+
if (severities.includes(severity.toUpperCase())) {
|
|
64
|
+
return severity.toLowerCase()
|
|
65
|
+
} else {
|
|
66
|
+
console.log(
|
|
67
|
+
severity +
|
|
68
|
+
' Not recognised as a severity type please use LOW, MEDIUM, HIGH, CRITICAL, NOTE'
|
|
69
|
+
)
|
|
70
|
+
return undefined
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
module.exports = {
|
|
75
|
+
failPipeline,
|
|
76
|
+
processFail,
|
|
77
|
+
isSeverityViolation,
|
|
78
|
+
parseSeverity
|
|
79
|
+
}
|
|
@@ -6,7 +6,7 @@ import commonApi from '../utils/commonApi'
|
|
|
6
6
|
import { constants } from 'http2'
|
|
7
7
|
import { ContrastConf } from '../utils/getConfig'
|
|
8
8
|
|
|
9
|
-
const getLatestVersion = async (config:
|
|
9
|
+
export const getLatestVersion = async (config: ContrastConf) => {
|
|
10
10
|
const client = commonApi.getHttpClient(config)
|
|
11
11
|
try {
|
|
12
12
|
const res = await client.getLatestVersion()
|
|
@@ -14,18 +14,28 @@ const getLatestVersion = async (config: any) => {
|
|
|
14
14
|
return res.body
|
|
15
15
|
}
|
|
16
16
|
} catch (e) {
|
|
17
|
-
return
|
|
17
|
+
return undefined
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
// @ts-ignore
|
|
22
21
|
export async function findLatestCLIVersion(config: ContrastConf) {
|
|
23
|
-
const
|
|
22
|
+
const isCI = process.env.CONTRAST_CODESEC_CI
|
|
23
|
+
? JSON.parse(process.env.CONTRAST_CODESEC_CI.toLowerCase())
|
|
24
|
+
: false
|
|
24
25
|
|
|
25
|
-
if (!
|
|
26
|
-
let latestCLIVersion
|
|
27
|
-
|
|
28
|
-
latestCLIVersion
|
|
26
|
+
if (!isCI) {
|
|
27
|
+
let latestCLIVersion = await getLatestVersion(config)
|
|
28
|
+
|
|
29
|
+
if (latestCLIVersion === undefined) {
|
|
30
|
+
config.set('numOfRuns', 0)
|
|
31
|
+
console.log(
|
|
32
|
+
'Failed to retrieve latest version info. Continuing execution.'
|
|
33
|
+
)
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
//strip key and remove new lines
|
|
38
|
+
latestCLIVersion = latestCLIVersion.substring(8).replace('\n', '')
|
|
29
39
|
|
|
30
40
|
if (semver.lt(APP_VERSION, latestCLIVersion)) {
|
|
31
41
|
const updateAvailableMessage = `Update available ${chalk.yellow(
|
|
@@ -14,7 +14,7 @@ const HIGH = 'HIGH'
|
|
|
14
14
|
const CRITICAL = 'CRITICAL'
|
|
15
15
|
// App
|
|
16
16
|
const APP_NAME = 'contrast'
|
|
17
|
-
const APP_VERSION = '1.0.
|
|
17
|
+
const APP_VERSION = '1.0.13'
|
|
18
18
|
const TIMEOUT = 120000
|
|
19
19
|
const HIGH_COLOUR = '#ff9900'
|
|
20
20
|
const CRITICAL_COLOUR = '#e35858'
|
|
@@ -32,7 +32,7 @@ const AUTH_CALLBACK_URL = 'https://cli-auth-api.contrastsecurity.com'
|
|
|
32
32
|
const SARIF_FILE = 'SARIF'
|
|
33
33
|
const SBOM_CYCLONE_DX_FILE = 'cyclonedx'
|
|
34
34
|
const SBOM_SPDX_FILE = 'spdx'
|
|
35
|
-
const CE_URL = 'https://ce.contrastsecurity.com
|
|
35
|
+
const CE_URL = 'https://ce.contrastsecurity.com'
|
|
36
36
|
|
|
37
37
|
module.exports = {
|
|
38
38
|
supportedLanguages: { NODE, DOTNET, JAVA, RUBY, PYTHON, GO, PHP, JAVASCRIPT },
|
package/src/constants/locales.js
CHANGED
|
@@ -26,8 +26,7 @@ const en_locales = () => {
|
|
|
26
26
|
unauthenticatedErrorMessage:
|
|
27
27
|
'Please check the following keys are correct:\n--organization-id, --api-key or --authorization',
|
|
28
28
|
badRequestErrorHeader: '400 error - Bad Request',
|
|
29
|
-
badRequestErrorMessage:
|
|
30
|
-
'Please check the following key is correct: \n--application-id',
|
|
29
|
+
badRequestErrorMessage: 'Please check your parameters and try again',
|
|
31
30
|
badRequestCatalogueErrorMessage:
|
|
32
31
|
'The application name already exists, please use a unique name',
|
|
33
32
|
forbiddenRequestErrorHeader: '403 error - Forbidden',
|
|
@@ -121,9 +120,11 @@ const en_locales = () => {
|
|
|
121
120
|
'The name of the application cataloged by Contrast UI',
|
|
122
121
|
constantsCatalogueApplication:
|
|
123
122
|
'Provide this if you want to catalogue an application',
|
|
123
|
+
failOptionErrorMessage:
|
|
124
|
+
' FAIL - CVEs have been detected that match at least the cve_severity option specified.',
|
|
124
125
|
constantsLanguage:
|
|
125
126
|
'Valid values are JAVA, DOTNET, NODE, PYTHON and RUBY. If there are multiple project configuration files in the project_path, language is also required. Also, provide this when cataloguing an application',
|
|
126
|
-
constantsFilePath: `
|
|
127
|
+
constantsFilePath: `Specify a directory or the file where dependencies are declared. (By default, CodeSec will search for project files in the current directory.)`,
|
|
127
128
|
constantsSilent: 'Silences JSON output.',
|
|
128
129
|
constantsAppGroups:
|
|
129
130
|
'Assign your application to one or more pre-existing groups when using the catalogue command. Group lists should be comma separated.',
|
|
@@ -142,8 +143,9 @@ const en_locales = () => {
|
|
|
142
143
|
constantsReport: 'Display vulnerability information for this application',
|
|
143
144
|
constantsFail:
|
|
144
145
|
'Set the process to fail if this option is set in combination with --cve_severity.',
|
|
145
|
-
|
|
146
|
-
|
|
146
|
+
failThresholdOptionErrorMessage: 'More than 0 vulnerabilities found',
|
|
147
|
+
failSeverityOptionErrorMessage:
|
|
148
|
+
' FAIL - Results detected vulnerabilities over accepted severity level',
|
|
147
149
|
constantsSeverity:
|
|
148
150
|
'Allows the user to report libraries with vulnerabilities above a chosen severity level. For example, cve_severity medium only reports libraries with vulnerabilities at medium or higher severity. Values for level are high, medium or low.',
|
|
149
151
|
constantsCount: 'The number of CVEs that must be exceeded to fail a build',
|
|
@@ -315,7 +317,7 @@ const en_locales = () => {
|
|
|
315
317
|
scanOptionsVerboseSummary: ' Returns extended information to the terminal.',
|
|
316
318
|
authSuccessMessage: 'Authentication successful',
|
|
317
319
|
runAuthSuccessMessage:
|
|
318
|
-
"Now you can use CodeSec by Contrast \nRun: \n'contrast scan'
|
|
320
|
+
"Now you can use CodeSec by Contrast \nRun: \n'contrast scan' to run CodeSec’s industry leading SAST scanner \n'contrast audit' to find vulnerabilities in your open source dependencies \n'contrast lambda' to secure your AWS serverless functions\nor 'contrast help' to learn more about the capabilities.",
|
|
319
321
|
authWaitingMessage: 'Waiting for auth...',
|
|
320
322
|
authTimedOutMessage: 'Auth Timed out, try again',
|
|
321
323
|
zipErrorScan:
|
|
@@ -414,7 +416,8 @@ const en_locales = () => {
|
|
|
414
416
|
auditOptionsSaveDescription:
|
|
415
417
|
'Generate and save an SBOM (Software Bill of Materials)\n',
|
|
416
418
|
auditOptionsSaveOptionsDescription:
|
|
417
|
-
'Valid options are: spdx
|
|
419
|
+
'Valid options are: --save spdx and --save cyclonedx (CycloneDX is the default format.)',
|
|
420
|
+
exceededFreeTier: `It looks like you are really loving CodeSec! \nYou have reached the monthly scan limit on the FREE tier. \nPlease contact sales@contrastsecurity.com to upgrade.`,
|
|
418
421
|
scanNotCompleted:
|
|
419
422
|
'Scan not completed. Check for framework and language support here: %s',
|
|
420
423
|
auditNotCompleted: 'audit not completed. Please try again',
|
|
@@ -437,6 +440,15 @@ const en_locales = () => {
|
|
|
437
440
|
auditReportFailureMessage: 'Unable to generate library report',
|
|
438
441
|
auditSCAAnalysisBegins: 'Contrast SCA audit started',
|
|
439
442
|
auditSCAAnalysisComplete: 'Contrast audit complete',
|
|
443
|
+
commonHelpHeader: 'Need More Help?',
|
|
444
|
+
commonHelpCheckOutHeader: chalk.hex('#9DC184')('Check out:'),
|
|
445
|
+
commonHelpCheckOutText: ' https://support.contrastsecurity.com',
|
|
446
|
+
commonHelpLearnMoreHeader: chalk.hex('#9DC184')('Learn more at:'),
|
|
447
|
+
commonHelpLearnMoreText: ' https://developer.contrastsecurity.com',
|
|
448
|
+
commonHelpJoinDiscussionHeader: chalk.hex('#9DC184')(
|
|
449
|
+
'Join the discussion:'
|
|
450
|
+
),
|
|
451
|
+
commonHelpJoinDiscussionText: ' https://dev.to/codesec',
|
|
440
452
|
...lambda
|
|
441
453
|
}
|
|
442
454
|
}
|
package/src/constants.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
const commandLineUsage = require('command-line-usage')
|
|
2
2
|
const i18n = require('i18n')
|
|
3
3
|
const { en_locales } = require('./constants/locales.js')
|
|
4
|
+
const { parseSeverity } = require('./common/fail')
|
|
5
|
+
const { commonHelpLinks } = require('./common/commonHelp')
|
|
4
6
|
|
|
5
7
|
i18n.configure({
|
|
6
8
|
staticCatalog: {
|
|
@@ -106,6 +108,24 @@ const scanOptionDefinitions = [
|
|
|
106
108
|
'}: ' +
|
|
107
109
|
i18n.__('constantsProxyServer')
|
|
108
110
|
},
|
|
111
|
+
{
|
|
112
|
+
name: 'fail',
|
|
113
|
+
type: Boolean,
|
|
114
|
+
description:
|
|
115
|
+
'{bold ' +
|
|
116
|
+
i18n.__('constantsOptional') +
|
|
117
|
+
'}: ' +
|
|
118
|
+
i18n.__('failOptionErrorMessage')
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
name: 'severity',
|
|
122
|
+
type: severity => parseSeverity(severity),
|
|
123
|
+
description:
|
|
124
|
+
'{bold ' +
|
|
125
|
+
i18n.__('constantsOptional') +
|
|
126
|
+
'}: ' +
|
|
127
|
+
i18n.__('constantsSeverity')
|
|
128
|
+
},
|
|
109
129
|
{
|
|
110
130
|
name: 'ff',
|
|
111
131
|
type: Boolean,
|
|
@@ -220,6 +240,24 @@ const auditOptionDefinitions = [
|
|
|
220
240
|
'}: ' +
|
|
221
241
|
i18n.__('constantsFilePath')
|
|
222
242
|
},
|
|
243
|
+
{
|
|
244
|
+
name: 'fail',
|
|
245
|
+
type: Boolean,
|
|
246
|
+
description:
|
|
247
|
+
'{bold ' +
|
|
248
|
+
i18n.__('constantsOptional') +
|
|
249
|
+
'}: ' +
|
|
250
|
+
i18n.__('failOptionErrorMessage')
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
name: 'severity',
|
|
254
|
+
type: severity => parseSeverity(severity),
|
|
255
|
+
description:
|
|
256
|
+
'{bold ' +
|
|
257
|
+
i18n.__('constantsOptional') +
|
|
258
|
+
'}: ' +
|
|
259
|
+
i18n.__('constantsSeverity')
|
|
260
|
+
},
|
|
223
261
|
{
|
|
224
262
|
name: 'app-groups',
|
|
225
263
|
description:
|
|
@@ -257,6 +295,7 @@ const auditOptionDefinitions = [
|
|
|
257
295
|
{
|
|
258
296
|
name: 'ignore-dev',
|
|
259
297
|
type: Boolean,
|
|
298
|
+
alias: 'i',
|
|
260
299
|
description:
|
|
261
300
|
'{bold ' +
|
|
262
301
|
i18n.__('constantsOptional') +
|
|
@@ -293,7 +332,6 @@ const auditOptionDefinitions = [
|
|
|
293
332
|
},
|
|
294
333
|
{
|
|
295
334
|
name: 'host',
|
|
296
|
-
alias: 'h',
|
|
297
335
|
description:
|
|
298
336
|
'{bold ' +
|
|
299
337
|
i18n.__('constantsRequired') +
|
|
@@ -341,6 +379,11 @@ const auditOptionDefinitions = [
|
|
|
341
379
|
i18n.__('constantsOptional') +
|
|
342
380
|
'}: ' +
|
|
343
381
|
i18n.__('scanOptionsTimeoutSummary')
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
name: 'help',
|
|
385
|
+
alias: 'h',
|
|
386
|
+
type: Boolean
|
|
344
387
|
}
|
|
345
388
|
]
|
|
346
389
|
|
|
@@ -368,16 +411,13 @@ const mainUsageGuide = commandLineUsage([
|
|
|
368
411
|
{ name: i18n.__('helpName'), summary: i18n.__('helpSummary') }
|
|
369
412
|
]
|
|
370
413
|
},
|
|
371
|
-
{
|
|
372
|
-
content:
|
|
373
|
-
'{underline https://developer.contrastsecurity.com/} \n For technical support head to {underline https://support.contrastsecurity.com}'
|
|
374
|
-
},
|
|
375
414
|
{
|
|
376
415
|
header: i18n.__('configHeader2'),
|
|
377
416
|
content: [
|
|
378
417
|
{ name: i18n.__('clearHeader'), summary: i18n.__('clearContent') }
|
|
379
418
|
]
|
|
380
|
-
}
|
|
419
|
+
},
|
|
420
|
+
commonHelpLinks()
|
|
381
421
|
])
|
|
382
422
|
|
|
383
423
|
const mainDefinition = [{ name: 'command', defaultOption: true }]
|