@contrast/contrast 1.0.20 → 1.0.22
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/cliConstants.js +17 -9
- package/dist/commands/audit/help.js +5 -1
- package/dist/commands/audit/processAudit.js +1 -1
- package/dist/commands/auth/auth.js +5 -0
- package/dist/commands/fingerprint/fingerprintConfig.js +12 -0
- package/dist/commands/fingerprint/processFingerprint.js +14 -0
- package/dist/commands/learn/learn.js +9 -0
- package/dist/commands/learn/processLearn.js +10 -0
- package/dist/common/HTTPClient.js +9 -0
- package/dist/common/commonHelp.js +8 -1
- package/dist/constants/constants.js +1 -1
- package/dist/constants/lambda.js +1 -0
- package/dist/constants/locales.js +20 -12
- package/dist/index.js +8 -0
- package/dist/lambda/help.js +5 -1
- package/dist/lambda/scanRequest.js +12 -1
- package/dist/scaAnalysis/common/treeUpload.js +3 -0
- package/dist/scaAnalysis/javascript/analysis.js +11 -33
- package/dist/scaAnalysis/javascript/index.js +14 -1
- package/dist/scaAnalysis/javascript/scaServiceParser.js +3 -3
- package/dist/scaAnalysis/scaAnalysis.js +155 -0
- package/dist/scan/autoDetection.js +2 -2
- package/dist/scan/fileUtils.js +2 -2
- package/dist/scan/help.js +5 -1
- package/dist/utils/settingsHelper.js +2 -2
- package/package.json +1 -1
- package/src/cliConstants.js +19 -9
- package/src/commands/audit/help.js +5 -1
- package/src/commands/audit/processAudit.js +1 -1
- package/src/commands/auth/auth.js +5 -0
- package/src/commands/fingerprint/fingerprintConfig.js +19 -0
- package/src/commands/fingerprint/processFingerprint.js +21 -0
- package/src/commands/learn/learn.js +10 -0
- package/src/commands/learn/processLearn.js +13 -0
- package/src/common/HTTPClient.js +11 -0
- package/src/common/commonHelp.js +11 -1
- package/src/constants/constants.js +1 -1
- package/src/constants/lambda.js +1 -0
- package/src/constants/locales.js +28 -12
- package/src/index.ts +10 -0
- package/src/lambda/help.ts +5 -1
- package/src/lambda/scanRequest.ts +27 -2
- package/src/scaAnalysis/common/treeUpload.js +7 -0
- package/src/scaAnalysis/javascript/analysis.js +19 -34
- package/src/scaAnalysis/javascript/index.js +29 -1
- package/src/scaAnalysis/javascript/scaServiceParser.js +3 -3
- package/src/scaAnalysis/scaAnalysis.js +206 -0
- package/src/scan/autoDetection.js +2 -2
- package/src/scan/fileUtils.js +2 -2
- package/src/scan/help.js +5 -1
- package/src/utils/settingsHelper.js +2 -2
- package/dist/commands/scan/sca/scaAnalysis.js +0 -157
- package/src/commands/scan/sca/scaAnalysis.js +0 -211
package/dist/cliConstants.js
CHANGED
|
@@ -186,6 +186,7 @@ const scanOptionDefinitions = [
|
|
|
186
186
|
];
|
|
187
187
|
const authOptionDefinitions = [
|
|
188
188
|
...sharedConnectionOptionDefinitions,
|
|
189
|
+
...sharedCertOptionDefinitions,
|
|
189
190
|
{
|
|
190
191
|
name: 'help',
|
|
191
192
|
alias: 'h',
|
|
@@ -296,10 +297,6 @@ const auditOptionDefinitions = [
|
|
|
296
297
|
'}: ' +
|
|
297
298
|
i18n.__('constantsIgnoreDev')
|
|
298
299
|
},
|
|
299
|
-
{
|
|
300
|
-
name: 'fingerprint',
|
|
301
|
-
type: Boolean
|
|
302
|
-
},
|
|
303
300
|
{
|
|
304
301
|
name: 'save',
|
|
305
302
|
alias: 's',
|
|
@@ -358,6 +355,14 @@ const auditOptionDefinitions = [
|
|
|
358
355
|
i18n.__('auditOptionsBranchSummary')
|
|
359
356
|
}
|
|
360
357
|
];
|
|
358
|
+
const fingerprintOptionDefinitions = [
|
|
359
|
+
...auditOptionDefinitions,
|
|
360
|
+
{
|
|
361
|
+
name: 'depth',
|
|
362
|
+
type: Number,
|
|
363
|
+
description: '{bold ' + i18n.__('constantsOptional') + '}: ' + i18n.__('depthOption')
|
|
364
|
+
}
|
|
365
|
+
];
|
|
361
366
|
const mainUsageGuide = commandLineUsage([
|
|
362
367
|
{
|
|
363
368
|
header: i18n.__('constantsHeader'),
|
|
@@ -374,12 +379,13 @@ const mainUsageGuide = commandLineUsage([
|
|
|
374
379
|
header: i18n.__('constantsCommands'),
|
|
375
380
|
content: [
|
|
376
381
|
{ name: i18n.__('authName'), summary: i18n.__('helpAuthSummary') },
|
|
382
|
+
{ name: i18n.__('configName'), summary: i18n.__('helpConfigSummary') },
|
|
383
|
+
{ name: i18n.__('versionName'), summary: i18n.__('helpVersionSummary') },
|
|
384
|
+
{ name: i18n.__('auditName'), summary: i18n.__('helpAuditSummary') },
|
|
377
385
|
{ name: i18n.__('scanName'), summary: i18n.__('helpScanSummary') },
|
|
378
386
|
{ name: i18n.__('lambdaName'), summary: i18n.__('helpLambdaSummary') },
|
|
379
|
-
{ name: i18n.__('
|
|
380
|
-
{ name: i18n.__('
|
|
381
|
-
{ name: i18n.__('configName'), summary: i18n.__('helpConfigSummary') },
|
|
382
|
-
{ name: i18n.__('helpName'), summary: i18n.__('helpSummary') }
|
|
387
|
+
{ name: i18n.__('helpName'), summary: i18n.__('helpSummary') },
|
|
388
|
+
{ name: i18n.__('learnName'), summary: i18n.__('helpLearnSummary') }
|
|
383
389
|
]
|
|
384
390
|
},
|
|
385
391
|
{
|
|
@@ -393,7 +399,8 @@ const mainUsageGuide = commandLineUsage([
|
|
|
393
399
|
]
|
|
394
400
|
},
|
|
395
401
|
commonHelpLinks()[0],
|
|
396
|
-
commonHelpLinks()[1]
|
|
402
|
+
commonHelpLinks()[1],
|
|
403
|
+
commonHelpLinks()[2]
|
|
397
404
|
]);
|
|
398
405
|
const mainDefinition = [{ name: 'command', defaultOption: true }];
|
|
399
406
|
module.exports = {
|
|
@@ -401,6 +408,7 @@ module.exports = {
|
|
|
401
408
|
mainUsageGuide,
|
|
402
409
|
mainDefinition,
|
|
403
410
|
scanOptionDefinitions,
|
|
411
|
+
fingerprintOptionDefinitions,
|
|
404
412
|
auditOptionDefinitions,
|
|
405
413
|
authOptionDefinitions,
|
|
406
414
|
configOptionDefinitions,
|
|
@@ -4,6 +4,9 @@ const i18n = require('i18n');
|
|
|
4
4
|
const constants = require('../../cliConstants');
|
|
5
5
|
const { commonHelpLinks } = require('../../common/commonHelp');
|
|
6
6
|
const auditUsageGuide = commandLineUsage([
|
|
7
|
+
{
|
|
8
|
+
header: i18n.__('constantsHeader')
|
|
9
|
+
},
|
|
7
10
|
{
|
|
8
11
|
header: i18n.__('auditHeader'),
|
|
9
12
|
content: [i18n.__('auditHeaderMessage')]
|
|
@@ -61,7 +64,8 @@ const auditUsageGuide = commandLineUsage([
|
|
|
61
64
|
optionList: constants.commandLineDefinitions.auditAdvancedOptionDefinitionsForHelp
|
|
62
65
|
},
|
|
63
66
|
commonHelpLinks()[0],
|
|
64
|
-
commonHelpLinks()[1]
|
|
67
|
+
commonHelpLinks()[1],
|
|
68
|
+
commonHelpLinks()[2]
|
|
65
69
|
]);
|
|
66
70
|
module.exports = {
|
|
67
71
|
auditUsageGuide
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const auditConfig = require('./auditConfig');
|
|
3
3
|
const { auditUsageGuide } = require('./help');
|
|
4
|
-
const scaController = require('
|
|
4
|
+
const scaController = require('../../scaAnalysis/scaAnalysis');
|
|
5
5
|
const { sendTelemetryConfigAsObject } = require('../../telemetry/telemetry');
|
|
6
6
|
const { postRunMessage } = require('../../common/commonHelp');
|
|
7
7
|
const processAudit = async (contrastConf, argvMain) => {
|
|
@@ -81,6 +81,11 @@ const authUsageGuide = commandLineUsage([
|
|
|
81
81
|
{
|
|
82
82
|
header: i18n.__('constantsAuthUsageHeader'),
|
|
83
83
|
content: [i18n.__('constantsAuthUsageContents')]
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
header: i18n.__('constantsAdvancedOptions'),
|
|
87
|
+
optionList: constants.commandLineDefinitions.authOptionDefinitions,
|
|
88
|
+
hide: ['organization-id', 'api-key', 'authorization', 'host']
|
|
84
89
|
}
|
|
85
90
|
]);
|
|
86
91
|
const checkForCustomCredentials = authParams => {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const parsedCLIOptions = require('../../utils/parsedCLIOptions');
|
|
3
|
+
const constants = require('../../cliConstants');
|
|
4
|
+
const paramHandler = require('../../utils/paramsUtil/paramHandler');
|
|
5
|
+
const getFingerprintConfig = async (contrastConf, command, argv) => {
|
|
6
|
+
const fingerprintParameters = await parsedCLIOptions.getCommandLineArgsCustom(contrastConf, command, argv, constants.commandLineDefinitions.fingerprintOptionDefinitions);
|
|
7
|
+
const paramsAuth = paramHandler.getAuth(fingerprintParameters);
|
|
8
|
+
return { ...paramsAuth, ...fingerprintParameters };
|
|
9
|
+
};
|
|
10
|
+
module.exports = {
|
|
11
|
+
getFingerprintConfig
|
|
12
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const fingerprintConfig = require('./fingerprintConfig');
|
|
3
|
+
const autoDetection = require('../../scan/autoDetection');
|
|
4
|
+
const saveResults = require('../../scan/saveResults');
|
|
5
|
+
const processFingerprint = async (contrastConf, argvMain) => {
|
|
6
|
+
const config = await fingerprintConfig.getFingerprintConfig(contrastConf, 'fingerprint', argvMain);
|
|
7
|
+
let fingerprint = await autoDetection.autoDetectFingerprintInfo(config.file, config.depth);
|
|
8
|
+
let idArray = fingerprint.map(x => x.id);
|
|
9
|
+
await saveResults.writeResultsToFile(fingerprint, 'fingerPrintInfo.json');
|
|
10
|
+
return console.log(idArray);
|
|
11
|
+
};
|
|
12
|
+
module.exports = {
|
|
13
|
+
processFingerprint
|
|
14
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const { openLearnPage } = require('./learn');
|
|
3
|
+
async function processLearn() {
|
|
4
|
+
console.log('Opening Contrast’s Secure Code Learning Hub...');
|
|
5
|
+
console.log('If the page does not open you can open it directly via https://www.contrastsecurity.com/developer/learn');
|
|
6
|
+
return openLearnPage();
|
|
7
|
+
}
|
|
8
|
+
module.exports = {
|
|
9
|
+
processLearn
|
|
10
|
+
};
|
|
@@ -191,6 +191,12 @@ HTTPClient.prototype.scaServiceIngests = function scaServiceIngests(config) {
|
|
|
191
191
|
options.url = url;
|
|
192
192
|
return requestUtils.sendRequest({ method: 'get', options });
|
|
193
193
|
};
|
|
194
|
+
HTTPClient.prototype.scaServiceHealth = function scaServiceIngests(config) {
|
|
195
|
+
const options = _.cloneDeep(this.requestOptions);
|
|
196
|
+
let url = createScaServiceHealthURL(config);
|
|
197
|
+
options.url = url;
|
|
198
|
+
return requestUtils.sendRequest({ method: 'get', options });
|
|
199
|
+
};
|
|
194
200
|
HTTPClient.prototype.getReportById = function getReportById(config, reportId) {
|
|
195
201
|
const options = _.cloneDeep(this.requestOptions);
|
|
196
202
|
if (config.ignoreDev) {
|
|
@@ -342,6 +348,9 @@ function createScaServiceReportStatusURL(config, reportId) {
|
|
|
342
348
|
function createScaServiceIngestsURL(config) {
|
|
343
349
|
return `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/applications/${config.applicationId}/libraries/ingests`;
|
|
344
350
|
}
|
|
351
|
+
function createScaServiceHealthURL(config) {
|
|
352
|
+
return `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/health`;
|
|
353
|
+
}
|
|
345
354
|
function createScaServiceIngestURL(config) {
|
|
346
355
|
let baseUrl = `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/applications/${config.applicationId}/libraries/ingests/tree`;
|
|
347
356
|
baseUrl = config.track ? baseUrl.concat('?persist=true') : baseUrl;
|
|
@@ -19,17 +19,24 @@ const commonHelpLinks = () => {
|
|
|
19
19
|
i18n.__('commonHelpLearnMoreEnterpriseHeader') +
|
|
20
20
|
i18n.__('commonHelpLearnMoreEnterpriseText')
|
|
21
21
|
]
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
content: [
|
|
25
|
+
i18n.__('commonHelpLearnHeader') + i18n.__('commonHelpLearnText')
|
|
26
|
+
]
|
|
22
27
|
}
|
|
23
28
|
];
|
|
24
29
|
};
|
|
25
30
|
const postRunMessage = commandName => {
|
|
26
31
|
console.log('\n' + chalk.underline.bold('Other Features:'));
|
|
27
32
|
if (commandName !== 'scan')
|
|
28
|
-
console.log("'contrast scan' to run
|
|
33
|
+
console.log("'contrast scan' to run Contrast's industry leading SAST scanner");
|
|
29
34
|
if (commandName !== 'audit')
|
|
30
35
|
console.log("'contrast audit' to find vulnerabilities in your open source dependencies");
|
|
31
36
|
if (commandName !== 'lambda')
|
|
32
37
|
console.log("'contrast lambda' to secure your AWS serverless functions");
|
|
38
|
+
if (commandName !== 'learn')
|
|
39
|
+
console.log("'contrast learn' launches Contrast's Secure Code Learning Hub.");
|
|
33
40
|
};
|
|
34
41
|
module.exports = {
|
|
35
42
|
commonHelpLinks,
|
|
@@ -12,7 +12,7 @@ const MEDIUM = 'MEDIUM';
|
|
|
12
12
|
const HIGH = 'HIGH';
|
|
13
13
|
const CRITICAL = 'CRITICAL';
|
|
14
14
|
const APP_NAME = 'contrast';
|
|
15
|
-
const APP_VERSION = '1.0.
|
|
15
|
+
const APP_VERSION = '1.0.22';
|
|
16
16
|
const TIMEOUT = 120000;
|
|
17
17
|
const HIGH_COLOUR = '#ff9900';
|
|
18
18
|
const CRITICAL_COLOUR = '#e35858';
|
package/dist/constants/lambda.js
CHANGED
|
@@ -48,6 +48,7 @@ const lambda = {
|
|
|
48
48
|
internal_error: 'Internal error',
|
|
49
49
|
inactive_account: 'Scanning a function of an inactive account is not supported',
|
|
50
50
|
not_supported_runtime: 'Scanning resource of runtime "{{runtime}}" is not supported.\nSupported runtimes: {{supportedRuntimes}}',
|
|
51
|
+
not_supported_lambda: 'This function cannot be scanned',
|
|
51
52
|
not_supported_onboard_account: 'Scanning a function of onboard account is not supported',
|
|
52
53
|
scan_lock: 'Other scan is still running. Please wait until the previous scan finishes',
|
|
53
54
|
unsupported: 'unsupported',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const { lambda } = require('./lambda');
|
|
3
3
|
const chalk = require('chalk');
|
|
4
|
+
const { APP_VERSION } = require('./constants');
|
|
4
5
|
const en_locales = () => {
|
|
5
6
|
return {
|
|
6
7
|
snapshotFailureHeader: 'FAIL',
|
|
@@ -52,7 +53,7 @@ const en_locales = () => {
|
|
|
52
53
|
failThresholdOptionErrorMessage: 'More than 0 vulnerabilities found',
|
|
53
54
|
failSeverityOptionErrorMessage: ' FAIL - Results detected vulnerabilities over accepted severity level',
|
|
54
55
|
constantsSeverity: '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.',
|
|
55
|
-
constantsHeader:
|
|
56
|
+
constantsHeader: `Contrast CLI @ v${APP_VERSION}`,
|
|
56
57
|
configHeader2: 'Config options',
|
|
57
58
|
clearHeader: '-c, --clear',
|
|
58
59
|
clearContent: 'Removes stored credentials',
|
|
@@ -107,10 +108,10 @@ const en_locales = () => {
|
|
|
107
108
|
genericServiceError: 'returned with status code %s',
|
|
108
109
|
permissionsError: 'You do not have the correct permissions here. \n Contact support@contrastsecurity.com to get this fixed.',
|
|
109
110
|
scanErrorFileMessage: 'We only accept the following file types: \nJava - .jar, .war \nJavaScript - .js or .zip files',
|
|
110
|
-
helpAuthSummary: 'Authenticate Contrast using your Github or Google account',
|
|
111
|
-
helpAuditSummary: 'Searches for a suitable file in the working directory to perform a security audit of dependencies and returns the results. [
|
|
112
|
-
helpScanSummary: 'Searches for a .jar, .war, .js, or .zip file in the working directory, uploads files for analysis, and returns the results. [
|
|
113
|
-
helpLambdaSummary: 'Performs a static security scan on an AWS lambda function. lambda --help
|
|
111
|
+
helpAuthSummary: 'Authenticate Contrast using your Github or Google account OR include credentials if you are an existing licensed Contrast user.',
|
|
112
|
+
helpAuditSummary: '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. ',
|
|
113
|
+
helpScanSummary: '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. ',
|
|
114
|
+
helpLambdaSummary: 'Performs a static security scan on an AWS lambda function. [lambda --help for options] AWS Lambda - Java & Python are supported. ',
|
|
114
115
|
helpVersionSummary: 'Displays version of Contrast CLI',
|
|
115
116
|
helpConfigSummary: 'Displays stored credentials',
|
|
116
117
|
helpSummary: 'Displays usage guide',
|
|
@@ -121,6 +122,10 @@ const en_locales = () => {
|
|
|
121
122
|
versionName: 'version',
|
|
122
123
|
configName: 'config',
|
|
123
124
|
helpName: 'help',
|
|
125
|
+
learnName: 'learn',
|
|
126
|
+
helpLearnSummary: 'Launches Contrast’s Secure Code Learning Hub.',
|
|
127
|
+
fingerprintName: 'assess repo to see how many languages it can detect. For use in pipeline only.',
|
|
128
|
+
depthOption: 'can set how deep in the file system the cli looks for language files',
|
|
124
129
|
scanOptionsLanguageSummary: 'Valid values are JAVA, JAVASCRIPT and DOTNET',
|
|
125
130
|
scanOptionsTimeoutSummary: 'Time in seconds to wait for scan to complete. Default value is 300 seconds.',
|
|
126
131
|
scanOptionsFileNameSummary: 'Path of the file you want to scan. If no file is specified, Contrast searches for a .jar, .war, .exe or .zip file in the working directory.',
|
|
@@ -136,7 +141,7 @@ const en_locales = () => {
|
|
|
136
141
|
chalk.bold('\ncontrast audit') +
|
|
137
142
|
' to find vulnerabilities in your open source dependencies.' +
|
|
138
143
|
'\nSupports Java, .NET, Node, Ruby, Python, Go and PHP.' +
|
|
139
|
-
'\nOur CLI runs native build tools to generate a complete dependency tree.' +
|
|
144
|
+
'\n\nOur CLI runs native build tools to generate a complete dependency tree.' +
|
|
140
145
|
'\nIf you are running on untrusted code, consider running in a sandbox.\n' +
|
|
141
146
|
chalk.bold('\ncontrast lambda') +
|
|
142
147
|
' to secure your AWS serverless functions. \nSupports Java and Python \n' +
|
|
@@ -148,7 +153,7 @@ const en_locales = () => {
|
|
|
148
153
|
foundDetailedVulnerabilities: chalk.bold('%s') + ' | ' + chalk.bold('%s') + ' | %s | %s | %s ',
|
|
149
154
|
searchingScanFileDirectory: 'Searching for file to scan from %s...',
|
|
150
155
|
searchingAuditFileDirectory: 'Searching for package manager files from %s...',
|
|
151
|
-
scanHeader:
|
|
156
|
+
scanHeader: `Contrast Scan CLI`,
|
|
152
157
|
authHeader: 'Auth',
|
|
153
158
|
lambdaHeader: 'Contrast Lambda CLI',
|
|
154
159
|
lambdaSummary: 'Performs static security scan on an AWS Lambda Function.\nProduces CVE (Vulnerable Dependencies) and Least Privilege violations/remediation results.',
|
|
@@ -179,7 +184,7 @@ const en_locales = () => {
|
|
|
179
184
|
connectionError: 'An error has occurred when trying to get the Project Id please check your internet connection or provide the Project Id manually',
|
|
180
185
|
internalServerErrorHeader: '500 error - Internal server error',
|
|
181
186
|
resourceLockedErrorHeader: '423 error - Resource is locked',
|
|
182
|
-
auditHeader: 'Contrast
|
|
187
|
+
auditHeader: 'Contrast Audit CLI',
|
|
183
188
|
auditHeaderMessage: "Use 'contrast audit' to analyze a project’s dependencies for vulnerabilities.",
|
|
184
189
|
constantsAuditPrerequisitesContentSupportedLanguages: 'Supported languages and their requirements are:',
|
|
185
190
|
constantsAuditPrerequisitesJavaContentMessage: `
|
|
@@ -219,12 +224,15 @@ const en_locales = () => {
|
|
|
219
224
|
commonHelpLearnMoreText: ' https://www.contrastsecurity.com/developer ',
|
|
220
225
|
commonHelpLearnMoreEnterpriseText: ' https://docs.contrastsecurity.com/en/run-contrast-cli.html ',
|
|
221
226
|
commonHelpJoinDiscussionHeader: chalk.hex('#9DC184')('Join the discussion:'),
|
|
222
|
-
commonHelpJoinDiscussionText: ' https://
|
|
227
|
+
commonHelpJoinDiscussionText: ' https://www.contrastsecurity.com/developer/community',
|
|
228
|
+
commonHelpLearnHeader: chalk.hex('#ffe599')('\r Want to UP your game?') +
|
|
229
|
+
" type 'contrast learn'",
|
|
230
|
+
commonHelpLearnText: `\n💰 Advance your security knowledge and become an ${chalk.hex('#ffd966')('All-star coder')} ⭐ with ${chalk.bold('Contrast Secure Code Learning Hub.')} 😺`,
|
|
223
231
|
authCommand: {
|
|
224
232
|
credentialsAccepted: {
|
|
225
|
-
title: 'Credentials
|
|
226
|
-
body: '
|
|
227
|
-
extra: '
|
|
233
|
+
title: '✔ Credentials successfully saved',
|
|
234
|
+
body: `\n${chalk.bold('Contrast CLI')}`,
|
|
235
|
+
extra: 'Scan, secure and ship your code in minutes.'
|
|
228
236
|
},
|
|
229
237
|
credentialsMissing: {
|
|
230
238
|
title: 'Credentials missing',
|
package/dist/index.js
CHANGED
|
@@ -9,6 +9,7 @@ const processAudit_1 = require("./commands/audit/processAudit");
|
|
|
9
9
|
const auth_1 = require("./commands/auth/auth");
|
|
10
10
|
const config_1 = require("./commands/config/config");
|
|
11
11
|
const processScan_1 = require("./commands/scan/processScan");
|
|
12
|
+
const processFingerprint_1 = require("./commands/fingerprint/processFingerprint");
|
|
12
13
|
const cliConstants_1 = __importDefault(require("./cliConstants"));
|
|
13
14
|
const constants_1 = require("./constants/constants");
|
|
14
15
|
const lambda_1 = require("./lambda/lambda");
|
|
@@ -16,6 +17,7 @@ const getConfig_1 = require("./utils/getConfig");
|
|
|
16
17
|
const versionChecker_1 = require("./common/versionChecker");
|
|
17
18
|
const errorHandling_1 = require("./common/errorHandling");
|
|
18
19
|
const telemetry_1 = require("./telemetry/telemetry");
|
|
20
|
+
const processLearn_1 = require("./commands/learn/processLearn");
|
|
19
21
|
const { commandLineDefinitions: { mainUsageGuide, mainDefinition } } = cliConstants_1.default;
|
|
20
22
|
const config = (0, getConfig_1.localConfig)(constants_1.APP_NAME, constants_1.APP_VERSION);
|
|
21
23
|
const getMainOption = () => {
|
|
@@ -64,6 +66,12 @@ const start = async () => {
|
|
|
64
66
|
if (command === 'audit') {
|
|
65
67
|
return await (0, processAudit_1.processAudit)(config, argvMain);
|
|
66
68
|
}
|
|
69
|
+
if (command === 'learn') {
|
|
70
|
+
return (0, processLearn_1.processLearn)();
|
|
71
|
+
}
|
|
72
|
+
if (command === 'fingerprint') {
|
|
73
|
+
return await (0, processFingerprint_1.processFingerprint)(config, argvMain);
|
|
74
|
+
}
|
|
67
75
|
if (command === 'help' ||
|
|
68
76
|
argvMain.includes('--help') ||
|
|
69
77
|
Object.keys(mainOptions).length === 0) {
|
package/dist/lambda/help.js
CHANGED
|
@@ -8,6 +8,9 @@ const command_line_usage_1 = __importDefault(require("command-line-usage"));
|
|
|
8
8
|
const i18n_1 = __importDefault(require("i18n"));
|
|
9
9
|
const commonHelp_1 = require("../common/commonHelp");
|
|
10
10
|
const lambdaUsageGuide = (0, command_line_usage_1.default)([
|
|
11
|
+
{
|
|
12
|
+
header: i18n_1.default.__('constantsHeader')
|
|
13
|
+
},
|
|
11
14
|
{
|
|
12
15
|
header: i18n_1.default.__('lambdaHeader'),
|
|
13
16
|
content: [i18n_1.default.__('lambdaSummary')]
|
|
@@ -82,6 +85,7 @@ const lambdaUsageGuide = (0, command_line_usage_1.default)([
|
|
|
82
85
|
]
|
|
83
86
|
},
|
|
84
87
|
(0, commonHelp_1.commonHelpLinks)()[0],
|
|
85
|
-
(0, commonHelp_1.commonHelpLinks)()[1]
|
|
88
|
+
(0, commonHelp_1.commonHelpLinks)()[1],
|
|
89
|
+
(0, commonHelp_1.commonHelpLinks)()[2]
|
|
86
90
|
]);
|
|
87
91
|
exports.lambdaUsageGuide = lambdaUsageGuide;
|
|
@@ -14,7 +14,9 @@ const commonApi_1 = require("../utils/commonApi");
|
|
|
14
14
|
const logUtils_1 = require("./logUtils");
|
|
15
15
|
const cliError_1 = require("./cliError");
|
|
16
16
|
const constants_1 = require("./constants");
|
|
17
|
-
const
|
|
17
|
+
const requestUtils_1 = require("../utils/requestUtils");
|
|
18
|
+
const MAX_RETRIES = 2;
|
|
19
|
+
const sendScanPostRequest = async (config, params, functionsEvent, showProgress = false, retryNumber = 0) => {
|
|
18
20
|
const client = (0, commonApi_1.getHttpClient)(config);
|
|
19
21
|
if (showProgress) {
|
|
20
22
|
(0, logUtils_1.log)(i18n_1.default.__('sendingScanRequest', { icon: log_symbols_1.default.success }));
|
|
@@ -38,6 +40,15 @@ const sendScanPostRequest = async (config, params, functionsEvent, showProgress
|
|
|
38
40
|
});
|
|
39
41
|
errorCode = false;
|
|
40
42
|
break;
|
|
43
|
+
case 'not_supported_lambda':
|
|
44
|
+
description = i18n_1.default.__(errorCode);
|
|
45
|
+
errorCode = false;
|
|
46
|
+
break;
|
|
47
|
+
default:
|
|
48
|
+
if (retryNumber < MAX_RETRIES) {
|
|
49
|
+
await (0, requestUtils_1.sleep)(3 * 1000);
|
|
50
|
+
return sendScanPostRequest(config, params, functionsEvent, showProgress, retryNumber + 1);
|
|
51
|
+
}
|
|
41
52
|
}
|
|
42
53
|
throw new cliError_1.CliError(constants_1.ERRORS.FAILED_TO_START_SCAN, {
|
|
43
54
|
statusCode,
|
|
@@ -18,6 +18,9 @@ const commonSendSnapShot = async (analysis, config) => {
|
|
|
18
18
|
return res.body;
|
|
19
19
|
}
|
|
20
20
|
else {
|
|
21
|
+
if (res.statusCode === 403) {
|
|
22
|
+
throw new Error(`🛑 Contrast audit failed \nPlease check you have the right permissions and the application ${config.applicationName ? config.applicationName : ''} has not been archived.`.replace(/ +(?= )/g, ''));
|
|
23
|
+
}
|
|
21
24
|
throw new Error(res.statusCode + ` error processing dependencies`);
|
|
22
25
|
}
|
|
23
26
|
})
|
|
@@ -32,46 +32,24 @@ const readYarn = async (config, languageFiles, nameOfFile) => {
|
|
|
32
32
|
throw new Error(i18n.__('nodeReadYarnLockFileError') + `${err.message}`);
|
|
33
33
|
}
|
|
34
34
|
};
|
|
35
|
-
const parseNpmLockFile = async (
|
|
35
|
+
const parseNpmLockFile = async (npmLockFile) => {
|
|
36
36
|
try {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const listOfTopDep = Object.keys(js.npmLockFile.dependencies);
|
|
40
|
-
Object.entries(js.npmLockFile.dependencies).forEach(([objKey, value]) => {
|
|
41
|
-
if (value.requires) {
|
|
42
|
-
const listOfRequiresDep = Object.keys(value.requires);
|
|
43
|
-
listOfRequiresDep.forEach(dep => {
|
|
44
|
-
if (!listOfTopDep.includes(dep)) {
|
|
45
|
-
addDepToLockFile(js, value['requires'], dep);
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
if (value.dependencies) {
|
|
50
|
-
Object.entries(value.dependencies).forEach(([objChildKey, childValue]) => {
|
|
51
|
-
if (childValue.requires) {
|
|
52
|
-
const listOfRequiresDep = Object.keys(childValue.requires);
|
|
53
|
-
listOfRequiresDep.forEach(dep => {
|
|
54
|
-
if (!listOfTopDep.includes(dep)) {
|
|
55
|
-
addDepToLockFile(js, childValue['requires'], dep);
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
return js.npmLockFile;
|
|
63
|
-
}
|
|
64
|
-
else {
|
|
65
|
-
return js.npmLockFile;
|
|
37
|
+
if (!npmLockFile.parsedPackages) {
|
|
38
|
+
npmLockFile.parsedPackages = {};
|
|
66
39
|
}
|
|
40
|
+
Object.entries(npmLockFile.packages).forEach(([packageKey, packageValue]) => {
|
|
41
|
+
if (packageKey.includes('node_modules/')) {
|
|
42
|
+
packageKey = packageKey.replace(/(node_modules\/)+/g, '');
|
|
43
|
+
}
|
|
44
|
+
npmLockFile.parsedPackages[packageKey] = packageValue;
|
|
45
|
+
});
|
|
46
|
+
delete npmLockFile.parsedPackages[''];
|
|
47
|
+
return npmLockFile;
|
|
67
48
|
}
|
|
68
49
|
catch (err) {
|
|
69
50
|
throw new Error(i18n.__('NodeParseNPM') + `${err.message}`);
|
|
70
51
|
}
|
|
71
52
|
};
|
|
72
|
-
const addDepToLockFile = (js, depObj, key) => {
|
|
73
|
-
return (js.npmLockFile.dependencies[key] = { version: depObj[key] });
|
|
74
|
-
};
|
|
75
53
|
const parseYarnLockFile = async (js) => {
|
|
76
54
|
try {
|
|
77
55
|
js.yarn.yarnLockFile = {};
|
|
@@ -32,7 +32,20 @@ const readFiles = async (config, files) => {
|
|
|
32
32
|
};
|
|
33
33
|
const parseFiles = async (config, files, js) => {
|
|
34
34
|
if (files.includes('package-lock.json')) {
|
|
35
|
-
|
|
35
|
+
const npmLockFile = JSON.parse(js.rawLockFileContents);
|
|
36
|
+
const currentLockFileVersion = npmLockFile.lockfileVersion;
|
|
37
|
+
const generalRebuildMessage = '\nPlease update to Node 16+ & NPM 8+ or 9+ and then rebuild your package files.' +
|
|
38
|
+
'\nMore info here: https://docs.npmjs.com/cli/v9/configuring-npm/package-lock-json';
|
|
39
|
+
if (currentLockFileVersion === 1) {
|
|
40
|
+
throw new Error(`NPM lockfileVersion 1 is no longer supported. \n ${generalRebuildMessage}`);
|
|
41
|
+
}
|
|
42
|
+
if (!currentLockFileVersion || !npmLockFile.packages) {
|
|
43
|
+
throw new Error(`package-lock.json needs to be in the NPM v2 or v3 format. \n ${generalRebuildMessage}`);
|
|
44
|
+
}
|
|
45
|
+
if (currentLockFileVersion === 3 && !config.experimental) {
|
|
46
|
+
throw new Error(`NPM lockfileVersion 3 is only supported when using the '-e' flag.`);
|
|
47
|
+
}
|
|
48
|
+
js.npmLockFile = await analysis.parseNpmLockFile(npmLockFile);
|
|
36
49
|
}
|
|
37
50
|
if (files.includes('yarn.lock')) {
|
|
38
51
|
js = await analysis.parseYarnLockFile(js);
|
|
@@ -47,7 +47,7 @@ const chooseLockFile = rawNode => {
|
|
|
47
47
|
return { lockFile: rawNode?.yarn?.yarnLockFile?.object, type: 'yarn' };
|
|
48
48
|
}
|
|
49
49
|
else if (rawNode.npmLockFile !== undefined) {
|
|
50
|
-
return { lockFile: rawNode?.npmLockFile?.
|
|
50
|
+
return { lockFile: rawNode?.npmLockFile?.parsedPackages, type: 'npm' };
|
|
51
51
|
}
|
|
52
52
|
else {
|
|
53
53
|
return undefined;
|
|
@@ -70,8 +70,8 @@ const createChildDependencies = (lockFileDep, currentDep) => {
|
|
|
70
70
|
};
|
|
71
71
|
const createNPMChildDependencies = (lockFileDep, currentDep) => {
|
|
72
72
|
let depArray = [];
|
|
73
|
-
if (lockFileDep[currentDep]?.
|
|
74
|
-
for (const [key, value] of Object.entries(lockFileDep[currentDep]?.
|
|
73
|
+
if (lockFileDep[currentDep]?.dependencies) {
|
|
74
|
+
for (const [key, value] of Object.entries(lockFileDep[currentDep]?.dependencies)) {
|
|
75
75
|
depArray.push(key);
|
|
76
76
|
}
|
|
77
77
|
}
|