@contrast/contrast 1.0.21 → 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 +4 -3
- package/dist/commands/audit/help.js +3 -0
- 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/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/scan/help.js +3 -0
- package/dist/utils/settingsHelper.js +2 -2
- package/package.json +1 -1
- package/src/cliConstants.js +4 -3
- package/src/commands/audit/help.js +3 -0
- 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/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/scan/help.js +3 -0
- package/src/utils/settingsHelper.js +2 -2
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',
|
|
@@ -378,11 +379,11 @@ const mainUsageGuide = commandLineUsage([
|
|
|
378
379
|
header: i18n.__('constantsCommands'),
|
|
379
380
|
content: [
|
|
380
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') },
|
|
381
385
|
{ name: i18n.__('scanName'), summary: i18n.__('helpScanSummary') },
|
|
382
386
|
{ name: i18n.__('lambdaName'), summary: i18n.__('helpLambdaSummary') },
|
|
383
|
-
{ name: i18n.__('auditName'), summary: i18n.__('helpAuditSummary') },
|
|
384
|
-
{ name: i18n.__('versionName'), summary: i18n.__('helpVersionSummary') },
|
|
385
|
-
{ name: i18n.__('configName'), summary: i18n.__('helpConfigSummary') },
|
|
386
387
|
{ name: i18n.__('helpName'), summary: i18n.__('helpSummary') },
|
|
387
388
|
{ name: i18n.__('learnName'), summary: i18n.__('helpLearnSummary') }
|
|
388
389
|
]
|
|
@@ -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')]
|
|
@@ -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 => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const { openLearnPage } = require('./learn');
|
|
3
3
|
async function processLearn() {
|
|
4
|
-
console.log('Opening
|
|
4
|
+
console.log('Opening Contrast’s Secure Code Learning Hub...');
|
|
5
5
|
console.log('If the page does not open you can open it directly via https://www.contrastsecurity.com/developer/learn');
|
|
6
6
|
return openLearnPage();
|
|
7
7
|
}
|
|
@@ -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;
|
|
@@ -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',
|
|
@@ -122,7 +123,7 @@ const en_locales = () => {
|
|
|
122
123
|
configName: 'config',
|
|
123
124
|
helpName: 'help',
|
|
124
125
|
learnName: 'learn',
|
|
125
|
-
helpLearnSummary: '
|
|
126
|
+
helpLearnSummary: 'Launches Contrast’s Secure Code Learning Hub.',
|
|
126
127
|
fingerprintName: 'assess repo to see how many languages it can detect. For use in pipeline only.',
|
|
127
128
|
depthOption: 'can set how deep in the file system the cli looks for language files',
|
|
128
129
|
scanOptionsLanguageSummary: 'Valid values are JAVA, JAVASCRIPT and DOTNET',
|
|
@@ -140,7 +141,7 @@ const en_locales = () => {
|
|
|
140
141
|
chalk.bold('\ncontrast audit') +
|
|
141
142
|
' to find vulnerabilities in your open source dependencies.' +
|
|
142
143
|
'\nSupports Java, .NET, Node, Ruby, Python, Go and PHP.' +
|
|
143
|
-
'\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.' +
|
|
144
145
|
'\nIf you are running on untrusted code, consider running in a sandbox.\n' +
|
|
145
146
|
chalk.bold('\ncontrast lambda') +
|
|
146
147
|
' to secure your AWS serverless functions. \nSupports Java and Python \n' +
|
|
@@ -152,7 +153,7 @@ const en_locales = () => {
|
|
|
152
153
|
foundDetailedVulnerabilities: chalk.bold('%s') + ' | ' + chalk.bold('%s') + ' | %s | %s | %s ',
|
|
153
154
|
searchingScanFileDirectory: 'Searching for file to scan from %s...',
|
|
154
155
|
searchingAuditFileDirectory: 'Searching for package manager files from %s...',
|
|
155
|
-
scanHeader:
|
|
156
|
+
scanHeader: `Contrast Scan CLI`,
|
|
156
157
|
authHeader: 'Auth',
|
|
157
158
|
lambdaHeader: 'Contrast Lambda CLI',
|
|
158
159
|
lambdaSummary: 'Performs static security scan on an AWS Lambda Function.\nProduces CVE (Vulnerable Dependencies) and Least Privilege violations/remediation results.',
|
|
@@ -183,7 +184,7 @@ const en_locales = () => {
|
|
|
183
184
|
connectionError: 'An error has occurred when trying to get the Project Id please check your internet connection or provide the Project Id manually',
|
|
184
185
|
internalServerErrorHeader: '500 error - Internal server error',
|
|
185
186
|
resourceLockedErrorHeader: '423 error - Resource is locked',
|
|
186
|
-
auditHeader: 'Contrast
|
|
187
|
+
auditHeader: 'Contrast Audit CLI',
|
|
187
188
|
auditHeaderMessage: "Use 'contrast audit' to analyze a project’s dependencies for vulnerabilities.",
|
|
188
189
|
constantsAuditPrerequisitesContentSupportedLanguages: 'Supported languages and their requirements are:',
|
|
189
190
|
constantsAuditPrerequisitesJavaContentMessage: `
|
|
@@ -224,14 +225,14 @@ const en_locales = () => {
|
|
|
224
225
|
commonHelpLearnMoreEnterpriseText: ' https://docs.contrastsecurity.com/en/run-contrast-cli.html ',
|
|
225
226
|
commonHelpJoinDiscussionHeader: chalk.hex('#9DC184')('Join the discussion:'),
|
|
226
227
|
commonHelpJoinDiscussionText: ' https://www.contrastsecurity.com/developer/community',
|
|
227
|
-
commonHelpLearnHeader: chalk.hex('#ffe599')('\
|
|
228
|
+
commonHelpLearnHeader: chalk.hex('#ffe599')('\r Want to UP your game?') +
|
|
228
229
|
" type 'contrast learn'",
|
|
229
|
-
commonHelpLearnText: `\n
|
|
230
|
+
commonHelpLearnText: `\n💰 Advance your security knowledge and become an ${chalk.hex('#ffd966')('All-star coder')} ⭐ with ${chalk.bold('Contrast Secure Code Learning Hub.')} 😺`,
|
|
230
231
|
authCommand: {
|
|
231
232
|
credentialsAccepted: {
|
|
232
|
-
title: 'Credentials
|
|
233
|
-
body: '
|
|
234
|
-
extra: '
|
|
233
|
+
title: '✔ Credentials successfully saved',
|
|
234
|
+
body: `\n${chalk.bold('Contrast CLI')}`,
|
|
235
|
+
extra: 'Scan, secure and ship your code in minutes.'
|
|
235
236
|
},
|
|
236
237
|
credentialsMissing: {
|
|
237
238
|
title: 'Credentials missing',
|
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')]
|
|
@@ -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
|
}
|
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
|
},
|
|
@@ -11,9 +11,9 @@ const getSettings = async (config) => {
|
|
|
11
11
|
const isSCAServicesAvailable = async (config) => {
|
|
12
12
|
const client = commonApi.getHttpClient(config);
|
|
13
13
|
return client
|
|
14
|
-
.
|
|
14
|
+
.scaServiceHealth(config)
|
|
15
15
|
.then(res => {
|
|
16
|
-
return res.
|
|
16
|
+
return res.body.status === 'UP';
|
|
17
17
|
})
|
|
18
18
|
.catch(err => {
|
|
19
19
|
console.log(err);
|
package/package.json
CHANGED
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')]
|
|
@@ -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, {
|
|
@@ -18,6 +18,13 @@ const commonSendSnapShot = async (analysis, config) => {
|
|
|
18
18
|
if (res.statusCode === 201) {
|
|
19
19
|
return res.body
|
|
20
20
|
} else {
|
|
21
|
+
if (res.statusCode === 403) {
|
|
22
|
+
throw new Error(
|
|
23
|
+
`🛑 Contrast audit failed \nPlease check you have the right permissions and the application ${
|
|
24
|
+
config.applicationName ? config.applicationName : ''
|
|
25
|
+
} has not been archived.`.replace(/ +(?= )/g, '')
|
|
26
|
+
)
|
|
27
|
+
}
|
|
21
28
|
throw new Error(res.statusCode + ` error processing dependencies`)
|
|
22
29
|
}
|
|
23
30
|
})
|
|
@@ -44,48 +44,33 @@ const readYarn = async (config, languageFiles, nameOfFile) => {
|
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
const parseNpmLockFile = async
|
|
47
|
+
const parseNpmLockFile = async npmLockFile => {
|
|
48
48
|
try {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
Object.entries(js.npmLockFile.dependencies).forEach(([objKey, value]) => {
|
|
53
|
-
if (value.requires) {
|
|
54
|
-
const listOfRequiresDep = Object.keys(value.requires)
|
|
55
|
-
listOfRequiresDep.forEach(dep => {
|
|
56
|
-
if (!listOfTopDep.includes(dep)) {
|
|
57
|
-
addDepToLockFile(js, value['requires'], dep)
|
|
58
|
-
}
|
|
59
|
-
})
|
|
60
|
-
}
|
|
49
|
+
if (!npmLockFile.parsedPackages) {
|
|
50
|
+
npmLockFile.parsedPackages = {}
|
|
51
|
+
}
|
|
61
52
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if (!listOfTopDep.includes(dep)) {
|
|
69
|
-
addDepToLockFile(js, childValue['requires'], dep)
|
|
70
|
-
}
|
|
71
|
-
})
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
)
|
|
53
|
+
Object.entries(npmLockFile.packages).forEach(
|
|
54
|
+
([packageKey, packageValue]) => {
|
|
55
|
+
if (packageKey.includes('node_modules/')) {
|
|
56
|
+
//remove object keys node modules prefixing
|
|
57
|
+
//e.g: node_modules/@aws-amplify/datastore/node_modules/uuid --> @aws-amplify/datastore/uuid
|
|
58
|
+
packageKey = packageKey.replace(/(node_modules\/)+/g, '')
|
|
75
59
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
60
|
+
|
|
61
|
+
npmLockFile.parsedPackages[packageKey] = packageValue
|
|
62
|
+
}
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
//remove base project package - unneeded
|
|
66
|
+
delete npmLockFile.parsedPackages['']
|
|
67
|
+
|
|
68
|
+
return npmLockFile
|
|
81
69
|
} catch (err) {
|
|
82
70
|
throw new Error(i18n.__('NodeParseNPM') + `${err.message}`)
|
|
83
71
|
}
|
|
84
72
|
}
|
|
85
73
|
|
|
86
|
-
const addDepToLockFile = (js, depObj, key) => {
|
|
87
|
-
return (js.npmLockFile.dependencies[key] = { version: depObj[key] })
|
|
88
|
-
}
|
|
89
74
|
const parseYarnLockFile = async js => {
|
|
90
75
|
try {
|
|
91
76
|
js.yarn.yarnLockFile = {}
|
|
@@ -14,9 +14,11 @@ const jsAnalysis = async (config, languageFiles) => {
|
|
|
14
14
|
const buildNodeTree = async (config, files) => {
|
|
15
15
|
let analysis = await readFiles(config, files)
|
|
16
16
|
const rawNode = await parseFiles(config, files, analysis)
|
|
17
|
+
|
|
17
18
|
if (config.experimental) {
|
|
18
19
|
return scaServiceParser.parseJS(rawNode)
|
|
19
20
|
}
|
|
21
|
+
|
|
20
22
|
return formatMessage.createJavaScriptTSMessage(rawNode)
|
|
21
23
|
}
|
|
22
24
|
|
|
@@ -44,8 +46,34 @@ const readFiles = async (config, files) => {
|
|
|
44
46
|
|
|
45
47
|
const parseFiles = async (config, files, js) => {
|
|
46
48
|
if (files.includes('package-lock.json')) {
|
|
47
|
-
|
|
49
|
+
const npmLockFile = JSON.parse(js.rawLockFileContents)
|
|
50
|
+
|
|
51
|
+
const currentLockFileVersion = npmLockFile.lockfileVersion
|
|
52
|
+
const generalRebuildMessage =
|
|
53
|
+
'\nPlease update to Node 16+ & NPM 8+ or 9+ and then rebuild your package files.' +
|
|
54
|
+
'\nMore info here: https://docs.npmjs.com/cli/v9/configuring-npm/package-lock-json'
|
|
55
|
+
|
|
56
|
+
if (currentLockFileVersion === 1) {
|
|
57
|
+
throw new Error(
|
|
58
|
+
`NPM lockfileVersion 1 is no longer supported. \n ${generalRebuildMessage}`
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (!currentLockFileVersion || !npmLockFile.packages) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
`package-lock.json needs to be in the NPM v2 or v3 format. \n ${generalRebuildMessage}`
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (currentLockFileVersion === 3 && !config.experimental) {
|
|
69
|
+
throw new Error(
|
|
70
|
+
`NPM lockfileVersion 3 is only supported when using the '-e' flag.`
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
js.npmLockFile = await analysis.parseNpmLockFile(npmLockFile)
|
|
48
75
|
}
|
|
76
|
+
|
|
49
77
|
if (files.includes('yarn.lock')) {
|
|
50
78
|
js = await analysis.parseYarnLockFile(js)
|
|
51
79
|
}
|
|
@@ -77,7 +77,7 @@ const chooseLockFile = rawNode => {
|
|
|
77
77
|
if (rawNode?.yarn?.yarnLockFile !== undefined) {
|
|
78
78
|
return { lockFile: rawNode?.yarn?.yarnLockFile?.object, type: 'yarn' }
|
|
79
79
|
} else if (rawNode.npmLockFile !== undefined) {
|
|
80
|
-
return { lockFile: rawNode?.npmLockFile?.
|
|
80
|
+
return { lockFile: rawNode?.npmLockFile?.parsedPackages, type: 'npm' }
|
|
81
81
|
} else {
|
|
82
82
|
return undefined
|
|
83
83
|
}
|
|
@@ -105,9 +105,9 @@ const createChildDependencies = (lockFileDep, currentDep) => {
|
|
|
105
105
|
|
|
106
106
|
const createNPMChildDependencies = (lockFileDep, currentDep) => {
|
|
107
107
|
let depArray = []
|
|
108
|
-
if (lockFileDep[currentDep]?.
|
|
108
|
+
if (lockFileDep[currentDep]?.dependencies) {
|
|
109
109
|
for (const [key, value] of Object.entries(
|
|
110
|
-
lockFileDep[currentDep]?.
|
|
110
|
+
lockFileDep[currentDep]?.dependencies
|
|
111
111
|
)) {
|
|
112
112
|
depArray.push(key)
|
|
113
113
|
}
|
package/src/scan/help.js
CHANGED
|
@@ -12,9 +12,9 @@ const getSettings = async config => {
|
|
|
12
12
|
const isSCAServicesAvailable = async config => {
|
|
13
13
|
const client = commonApi.getHttpClient(config)
|
|
14
14
|
return client
|
|
15
|
-
.
|
|
15
|
+
.scaServiceHealth(config)
|
|
16
16
|
.then(res => {
|
|
17
|
-
return res.
|
|
17
|
+
return res.body.status === 'UP'
|
|
18
18
|
})
|
|
19
19
|
.catch(err => {
|
|
20
20
|
console.log(err)
|