@contrast/contrast 1.0.9 → 1.0.10

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 CHANGED
@@ -52,7 +52,7 @@ export AWS_SECRET_ACCESS_KEY=<YOUR_SECRET_ACCESS_KEY>
52
52
 
53
53
  - These permissions are required to gather all required information on an AWS Lambda to use the `contrast lambda` command:
54
54
 
55
- - Lambda: [GetFunction](https://docs.aws.amazon.com/lambda/latest/dg/API_GetFunction.html) | [GetLayerVersion](https://docs.aws.amazon.com/lambda/latest/dg/API_GetLayerVersion.html)
55
+ - Lambda: [GetFunction](https://docs.aws.amazon.com/lambda/latest/dg/API_GetFunction.html) | [GetLayerVersion](https://docs.aws.amazon.com/lambda/latest/dg/API_GetLayerVersion.html) | [ListFunctions](https://docs.aws.amazon.com/lambda/latest/dg/API_ListFunctions.html)
56
56
  - IAM: [GetRolePolicy](https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetRolePolicy.html) | [GetPolicy](https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetPolicy.html) | [GetPolicyVersion](https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetPolicyVersion.html) | [ListRolePolicies](https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListRolePolicies.html) | [ListAttachedRolePolicies](https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListAttachedRolePolicies.html)
57
57
 
58
58
  ### Start scanning
@@ -2,29 +2,29 @@
2
2
  const fs = require('fs');
3
3
  const path = require('path');
4
4
  const i18n = require('i18n');
5
- const getProjectRootFilenames = file => {
6
- let projectStats = null;
5
+ const getDirectoryFromPathGiven = file => {
6
+ let projectStats = getProjectStats(file);
7
+ if (projectStats.isFile()) {
8
+ let newPath = path.resolve(file);
9
+ return path.dirname(newPath);
10
+ }
11
+ if (projectStats.isDirectory()) {
12
+ return file;
13
+ }
14
+ };
15
+ const getProjectStats = file => {
7
16
  try {
8
- projectStats = fs.statSync(file);
17
+ if (file.endsWith('/')) {
18
+ file = file.slice(0, -1);
19
+ }
20
+ return fs.statSync(file);
9
21
  }
10
22
  catch (err) {
11
23
  throw new Error(i18n.__('languageAnalysisProjectRootFileNameFailure', file) +
12
24
  `${err.message}`);
13
25
  }
14
- if (projectStats.isDirectory()) {
15
- try {
16
- return fs.readdirSync(file);
17
- }
18
- catch (err) {
19
- throw new Error(i18n.__('languageAnalysisProjectRootFileNameReadError', file) +
20
- `${err.message}`);
21
- }
22
- }
23
- if (projectStats.isFile()) {
24
- return [path.basename(file)];
25
- }
26
- throw new Error(i18n.__('languageAnalysisProjectRootFileNameMissingError'), file);
27
26
  };
28
27
  module.exports = {
29
- getProjectRootFilenames
28
+ getProjectStats,
29
+ getDirectoryFromPathGiven: getDirectoryFromPathGiven
30
30
  };
@@ -15,16 +15,20 @@ const i18n = require('i18n');
15
15
  const { vulnerabilityReportV2 } = require('../../../audit/languageAnalysisEngine/report/reportingFeature');
16
16
  const auditSave = require('../../../audit/save');
17
17
  const { dotNetAnalysis } = require('../../../scaAnalysis/dotnet');
18
+ const rootFile = require('../../../audit/languageAnalysisEngine/getProjectRootFilenames');
19
+ const path = require('path');
18
20
  const processSca = async (config) => {
19
21
  const startTime = performance.now();
20
22
  let filesFound;
21
- if (config.file) {
22
- config.file = config.file.concat('/');
23
- filesFound = await autoDetection.autoDetectAuditFilesAndLanguages(config.file);
24
- }
25
- else {
26
- filesFound = await autoDetection.autoDetectAuditFilesAndLanguages(undefined);
27
- config.file = process.cwd().concat('/');
23
+ const projectStats = await rootFile.getProjectStats(config.file);
24
+ let pathWithFile = projectStats.isFile();
25
+ let fileName = config.file;
26
+ config.file = pathWithFile
27
+ ? rootFile.getDirectoryFromPathGiven(config.file).concat('/')
28
+ : config.file;
29
+ filesFound = await autoDetection.autoDetectAuditFilesAndLanguages(config.file);
30
+ if (filesFound.length > 1 && pathWithFile) {
31
+ filesFound = filesFound.filter(i => Object.values(i)[0].includes(path.basename(fileName)));
28
32
  }
29
33
  let messageToSend = undefined;
30
34
  if (filesFound.length === 1) {
@@ -48,8 +48,8 @@ const reportFailureError = () => {
48
48
  };
49
49
  exports.reportFailureError = reportFailureError;
50
50
  const genericError = (missingCliOption) => {
51
- console.log(`*************************** ${i18n_1.default.__('yamlMissingParametersHeader')} ***************************\n${missingCliOption}`);
52
- console.error(i18n_1.default.__('yamlMissingParametersMessage'));
51
+ console.log(missingCliOption);
52
+ console.error(i18n_1.default.__('genericErrorMessage'));
53
53
  process.exit(1);
54
54
  };
55
55
  exports.genericError = genericError;
@@ -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.9';
15
+ const APP_VERSION = '1.0.10';
16
16
  const TIMEOUT = 120000;
17
17
  const HIGH_COLOUR = '#ff9900';
18
18
  const CRITICAL_COLOUR = '#e35858';
@@ -16,7 +16,7 @@ const en_locales = () => {
16
16
  languageAnalysisFactoryFailureHeader: 'FAIL',
17
17
  libraryAnalysisError: 'Please ensure the language parameter is set in accordance to the language specified on the project path.\nContrast CLI must be run in the same directory as the project manifest file OR the project_path parameter must be used to identify the directory containing the project manifest file.\n\nFor further information please read our usage guide, which can be accessed with the following command:\n\ncontrast-cli --help',
18
18
  yamlMissingParametersHeader: 'Missing Parameters',
19
- yamlMissingParametersMessage: 'The following parameters are required: \n \norganization-id \napi-key \nauthorization \nhost \nlanguage \n \nThey must be specified as a command line argument. \nFor further information please read our usage guide, which can be accessed with the following command:\ncontrast audit --help',
19
+ genericErrorMessage: 'An error has occur please check your command again. For more information use the --help commands.',
20
20
  unauthenticatedErrorHeader: '401 error - Unauthenticated',
21
21
  unauthenticatedErrorMessage: 'Please check the following keys are correct:\n--organization-id, --api-key or --authorization',
22
22
  badRequestErrorHeader: '400 error - Bad Request',
@@ -45,7 +45,7 @@ const en_locales = () => {
45
45
  languageAnalysisProjectRootFileNameMissingError: "%s isn't a file or directory",
46
46
  languageAnalysisProjectRootFileNameFailure: 'Failed to get information about the file or directory @ %s because: ',
47
47
  languageAnalysisFailure: ' analysis failed because: ',
48
- languageAnalysisNoLanguage: 'We cannot detect a project, use --f <path> to specify a file or folder to analyze.',
48
+ languageAnalysisNoLanguage: 'We cannot detect a project, use -f <path> to specify a file or folder to analyze.',
49
49
  languageAnalysisNoLanguageHelpLine: `${chalk.bold('contrast audit --help')} for more information.`,
50
50
  NodeAnalysisFailure: 'NODE analysis failed because: ',
51
51
  phpAnalysisFailure: 'PHP analysis failed because: ',
@@ -97,8 +97,12 @@ const en_locales = () => {
97
97
  constantsSeverity: '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.',
98
98
  constantsCount: 'The number of CVEs that must be exceeded to fail a build',
99
99
  constantsHeader: 'CodeSec by Contrast Security',
100
+ configHeader2: 'Config options',
101
+ clearHeader: '-c, --clear',
102
+ clearContent: 'Removes stored credentials',
100
103
  constantsPrerequisitesContentScanLanguages: 'Java, Javascript and .NET supported',
101
- constantsContrastContent: "Use the 'contrast' command for fast and accurate security analysis of your applications and APIs (Java, JavaScript and .NET ) as well as serverless functions (AWS lambda, Java and Python).",
104
+ constantsContrastContent: 'Use the contrast command for fast and accurate security analysis of your applications, APIs, serverless functions, and libraries.',
105
+ constantsContrastCategories: '\n Code: Java, .NET, .NET Core, JavaScript\n Serverless: AWS Lambda - Java, Python\n Libraries: Java, .NET, Node, Ruby, Python, Go, PHP\n',
102
106
  constantsUsageGuideContentRecommendation: 'Our recommendation is that this is invoked as part of a CI pipeline so that running the cli is automated as part of your build process.',
103
107
  constantsPrerequisitesHeader: 'Pre-requisites',
104
108
  constantsAuthUsageHeader: 'Usage',
@@ -187,12 +191,14 @@ const en_locales = () => {
187
191
  permissionsError: 'You do not have the correct permissions here. \n Contact support@contrastsecurity.com to get this fixed.',
188
192
  scanErrorFileMessage: 'We only accept the following file types: \nJava - .jar, .war \nJavaScript - .js or .zip files',
189
193
  helpAuthSummary: 'Authenticate Contrast using your Github or Google account',
190
- helpScanSummary: 'Perform static analysis on binaries / code artifacts',
191
- helpLambdaSummary: 'Perform scan on AWS Lambda functions',
194
+ helpAuditSummary: 'Searches for a suitable file in the working directory to perform a security audit of dependencies and returns the results. [Contrast audit --help (for options).]',
195
+ helpScanSummary: 'Searches for a .jar, .war, .js, or .zip file in the working directory, uploads files for analysis, and returns the results. [For further help/options, enter scan --help]',
196
+ helpLambdaSummary: 'Performs a static security scan on an AWS lambda function. lambda --help (for options)',
192
197
  helpVersionSummary: 'Displays version of Contrast CLI',
193
198
  helpConfigSummary: 'Displays stored credentials',
194
199
  helpSummary: 'Displays usage guide',
195
200
  authName: 'auth',
201
+ auditName: 'audit',
196
202
  scanName: 'scan',
197
203
  lambdaName: 'lambda',
198
204
  versionName: 'version',
@@ -205,8 +211,7 @@ const en_locales = () => {
205
211
  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.',
206
212
  scanOptionsVerboseSummary: ' Returns extended information to the terminal.',
207
213
  authSuccessMessage: 'Authentication successful',
208
- runAuthSuccessMessage: "Now you can use Contrast CLI \nRun 'contrast scan' on your file \n" +
209
- "or 'contrast help' to learn more about the capabilities.",
214
+ runAuthSuccessMessage: "Now you can use CodeSec by Contrast \nRun: \n'contrast scan' on your file \n'contrast audit' on a file or directory,\n'contrast lambda' on an AWS function.\nor 'contrast help' to learn more about the capabilities.",
210
215
  authWaitingMessage: 'Waiting for auth...',
211
216
  authTimedOutMessage: 'Auth Timed out, try again',
212
217
  zipErrorScan: 'We only support zip files for JAVASCRIPT language, please set the flag --language JAVASCRIPT',
@@ -228,7 +233,7 @@ const en_locales = () => {
228
233
  lambdaPrerequisitesContent: '',
229
234
  lambdaPrerequisitesContentLambdaLanguages: 'Supported runtimes: Java & Python',
230
235
  lambdaPrerequisitesContentLambdaDescriptionTitle: 'AWS Requirements\n',
231
- lambdaPrerequisitesContentLambdaDescription: 'Make sure you have the AWS credentials configured on your local environment. \nYou need the following AWS permissions configured on your IAM user:\n - Lambda: GetFunction, GetLayerVersionֿ\n - IAM: GetRolePolicy, GetPolicy, GetPolicyVersion, ListRolePolicies, ListAttachedRolePolicies',
236
+ lambdaPrerequisitesContentLambdaDescription: 'Make sure you have the AWS credentials configured on your local environment. \nYou need the following AWS permissions configured on your IAM user:\n - Lambda: GetFunction, GetLayerVersion, ListFunctions\n - IAM: GetRolePolicy, GetPolicy, GetPolicyVersion, ListRolePolicies, ListAttachedRolePolicies',
232
237
  scanFileNameOption: '-f, --file',
233
238
  lambdaFunctionNameOption: '-f, --function-name',
234
239
  lambdaListFunctionsOption: '-l, --list-functions',
package/dist/constants.js CHANGED
@@ -189,7 +189,7 @@ const auditOptionDefinitions = [
189
189
  {
190
190
  name: 'file',
191
191
  alias: 'f',
192
- defaultValue: process.cwd(),
192
+ defaultValue: process.cwd().concat('/'),
193
193
  description: '{bold ' +
194
194
  i18n.__('constantsOptional') +
195
195
  '}: ' +
@@ -307,7 +307,10 @@ const auditOptionDefinitions = [
307
307
  const mainUsageGuide = commandLineUsage([
308
308
  {
309
309
  header: i18n.__('constantsHeader'),
310
- content: [i18n.__('constantsContrastContent')]
310
+ content: [
311
+ i18n.__('constantsContrastContent'),
312
+ i18n.__('constantsContrastCategories')
313
+ ]
311
314
  },
312
315
  {
313
316
  header: i18n.__('constantsUsage'),
@@ -319,6 +322,7 @@ const mainUsageGuide = commandLineUsage([
319
322
  { name: i18n.__('authName'), summary: i18n.__('helpAuthSummary') },
320
323
  { name: i18n.__('scanName'), summary: i18n.__('helpScanSummary') },
321
324
  { name: i18n.__('lambdaName'), summary: i18n.__('helpLambdaSummary') },
325
+ { name: i18n.__('auditName'), summary: i18n.__('helpAuditSummary') },
322
326
  { name: i18n.__('versionName'), summary: i18n.__('helpVersionSummary') },
323
327
  { name: i18n.__('configName'), summary: i18n.__('helpConfigSummary') },
324
328
  { name: i18n.__('helpName'), summary: i18n.__('helpSummary') }
@@ -326,6 +330,12 @@ const mainUsageGuide = commandLineUsage([
326
330
  },
327
331
  {
328
332
  content: '{underline https://developer.contrastsecurity.com/} \n For technical support head to {underline https://support.contrastsecurity.com}'
333
+ },
334
+ {
335
+ header: i18n.__('configHeader2'),
336
+ content: [
337
+ { name: i18n.__('clearHeader'), summary: i18n.__('clearContent') }
338
+ ]
329
339
  }
330
340
  ]);
331
341
  const mainDefinition = [{ name: 'command', defaultOption: true }];
@@ -4,6 +4,9 @@ const i18n = require('i18n');
4
4
  const formatMessage = require('../common/formatMessage');
5
5
  const jsAnalysis = async (config, languageFiles) => {
6
6
  checkForCorrectFiles(languageFiles);
7
+ if (!config.file.endsWith('/')) {
8
+ config.file = config.file.concat('/');
9
+ }
7
10
  return buildNodeTree(config, languageFiles.JAVASCRIPT);
8
11
  };
9
12
  const buildNodeTree = async (config, files) => {
@@ -2,6 +2,7 @@
2
2
  const i18n = require('i18n');
3
3
  const fileFinder = require('./fileUtils');
4
4
  const rootFile = require('../audit/languageAnalysisEngine/getProjectRootFilenames');
5
+ const path = require('path');
5
6
  const autoDetectFileAndLanguage = async (configToUse) => {
6
7
  const entries = await fileFinder.findFile();
7
8
  if (entries.length === 1) {
@@ -23,16 +24,9 @@ const autoDetectFileAndLanguage = async (configToUse) => {
23
24
  errorOnFileDetection(entries);
24
25
  }
25
26
  };
26
- const autoDetectAuditFilesAndLanguages = async (file) => {
27
- const filePath = file;
27
+ const autoDetectAuditFilesAndLanguages = async (filePath) => {
28
28
  let languagesFound = [];
29
- if (filePath) {
30
- rootFile.getProjectRootFilenames(filePath);
31
- console.log(i18n.__('searchingAuditFileDirectory', filePath));
32
- }
33
- else {
34
- console.log(i18n.__('searchingAuditFileDirectory', process.cwd()));
35
- }
29
+ console.log(i18n.__('searchingAuditFileDirectory', filePath));
36
30
  await fileFinder.findFilesJava(languagesFound, filePath);
37
31
  await fileFinder.findFilesJavascript(languagesFound, filePath);
38
32
  await fileFinder.findFilesPython(languagesFound, filePath);
@@ -40,12 +34,10 @@ const autoDetectAuditFilesAndLanguages = async (file) => {
40
34
  await fileFinder.findFilesPhp(languagesFound, filePath);
41
35
  await fileFinder.findFilesRuby(languagesFound, filePath);
42
36
  await fileFinder.findFilesDotNet(languagesFound, filePath);
43
- if (languagesFound.length <= 1) {
37
+ if (languagesFound) {
44
38
  return languagesFound;
45
39
  }
46
- else {
47
- console.log('found multiple languages, please specify one using --file to run SCA audit');
48
- }
40
+ return [];
49
41
  };
50
42
  const hasWhiteSpace = s => {
51
43
  const filename = s.split('/').pop();
@@ -18,7 +18,7 @@ const handleResponseErrors = (res, api) => {
18
18
  maxAppError();
19
19
  }
20
20
  else {
21
- genericError();
21
+ genericError(res);
22
22
  }
23
23
  };
24
24
  const getProtocol = host => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrast/contrast",
3
- "version": "1.0.9",
3
+ "version": "1.0.10",
4
4
  "description": "Contrast Security's command line tool",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -2,42 +2,35 @@ const fs = require('fs')
2
2
  const path = require('path')
3
3
  const i18n = require('i18n')
4
4
 
5
- const getProjectRootFilenames = file => {
6
- let projectStats = null
5
+ const getDirectoryFromPathGiven = file => {
6
+ let projectStats = getProjectStats(file)
7
+
8
+ if (projectStats.isFile()) {
9
+ let newPath = path.resolve(file)
10
+ return path.dirname(newPath)
11
+ }
12
+
13
+ if (projectStats.isDirectory()) {
14
+ return file
15
+ }
16
+ }
17
+
18
+ const getProjectStats = file => {
7
19
  try {
8
- projectStats = fs.statSync(file)
20
+ //might not need this
21
+ if (file.endsWith('/')) {
22
+ file = file.slice(0, -1)
23
+ }
24
+ return fs.statSync(file)
9
25
  } catch (err) {
10
26
  throw new Error(
11
27
  i18n.__('languageAnalysisProjectRootFileNameFailure', file) +
12
28
  `${err.message}`
13
29
  )
14
30
  }
15
-
16
- // Return the contents of a directory...
17
- if (projectStats.isDirectory()) {
18
- try {
19
- return fs.readdirSync(file)
20
- } catch (err) {
21
- throw new Error(
22
- i18n.__('languageAnalysisProjectRootFileNameReadError', file) +
23
- `${err.message}`
24
- )
25
- }
26
- }
27
-
28
- // If we are working with a file return it in a list as we do when we work
29
- // with a directory...
30
- if (projectStats.isFile()) {
31
- return [path.basename(file)]
32
- }
33
-
34
- // Error out if we are working with something like a socket file or some
35
- // other craziness...
36
- throw new Error(
37
- i18n.__('languageAnalysisProjectRootFileNameMissingError'),
38
- file
39
- )
40
31
  }
32
+
41
33
  module.exports = {
42
- getProjectRootFilenames
34
+ getProjectStats,
35
+ getDirectoryFromPathGiven: getDirectoryFromPathGiven
43
36
  }
@@ -24,17 +24,26 @@ const {
24
24
  } = require('../../../audit/languageAnalysisEngine/report/reportingFeature')
25
25
  const auditSave = require('../../../audit/save')
26
26
  const { dotNetAnalysis } = require('../../../scaAnalysis/dotnet')
27
+ const rootFile = require('../../../audit/languageAnalysisEngine/getProjectRootFilenames')
28
+ const path = require('path')
27
29
  const processSca = async config => {
28
30
  const startTime = performance.now()
29
31
  let filesFound
30
- if (config.file) {
31
- config.file = config.file.concat('/')
32
- filesFound = await autoDetection.autoDetectAuditFilesAndLanguages(
33
- config.file
32
+
33
+ const projectStats = await rootFile.getProjectStats(config.file)
34
+ let pathWithFile = projectStats.isFile()
35
+
36
+ let fileName = config.file
37
+ config.file = pathWithFile
38
+ ? rootFile.getDirectoryFromPathGiven(config.file).concat('/')
39
+ : config.file
40
+
41
+ filesFound = await autoDetection.autoDetectAuditFilesAndLanguages(config.file)
42
+
43
+ if (filesFound.length > 1 && pathWithFile) {
44
+ filesFound = filesFound.filter(i =>
45
+ Object.values(i)[0].includes(path.basename(fileName))
34
46
  )
35
- } else {
36
- filesFound = await autoDetection.autoDetectAuditFilesAndLanguages(undefined)
37
- config.file = process.cwd().concat('/')
38
47
  }
39
48
 
40
49
  // files found looks like [ { javascript: [ Array ] } ]
@@ -39,9 +39,8 @@ const reportFailureError = () => {
39
39
  }
40
40
 
41
41
  const genericError = (missingCliOption: string) => {
42
- // prettier-ignore
43
- console.log(`*************************** ${i18n.__('yamlMissingParametersHeader')} ***************************\n${missingCliOption}`)
44
- console.error(i18n.__('yamlMissingParametersMessage'))
42
+ console.log(missingCliOption)
43
+ console.error(i18n.__('genericErrorMessage'))
45
44
  process.exit(1)
46
45
  }
47
46
 
@@ -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.9'
17
+ const APP_VERSION = '1.0.10'
18
18
  const TIMEOUT = 120000
19
19
  const HIGH_COLOUR = '#ff9900'
20
20
  const CRITICAL_COLOUR = '#e35858'
@@ -20,8 +20,8 @@ const en_locales = () => {
20
20
  libraryAnalysisError:
21
21
  'Please ensure the language parameter is set in accordance to the language specified on the project path.\nContrast CLI must be run in the same directory as the project manifest file OR the project_path parameter must be used to identify the directory containing the project manifest file.\n\nFor further information please read our usage guide, which can be accessed with the following command:\n\ncontrast-cli --help',
22
22
  yamlMissingParametersHeader: 'Missing Parameters',
23
- yamlMissingParametersMessage:
24
- 'The following parameters are required: \n \norganization-id \napi-key \nauthorization \nhost \nlanguage \n \nThey must be specified as a command line argument. \nFor further information please read our usage guide, which can be accessed with the following command:\ncontrast audit --help',
23
+ genericErrorMessage:
24
+ 'An error has occur please check your command again. For more information use the --help commands.',
25
25
  unauthenticatedErrorHeader: '401 error - Unauthenticated',
26
26
  unauthenticatedErrorMessage:
27
27
  'Please check the following keys are correct:\n--organization-id, --api-key or --authorization',
@@ -67,7 +67,7 @@ const en_locales = () => {
67
67
  'Failed to get information about the file or directory @ %s because: ',
68
68
  languageAnalysisFailure: ' analysis failed because: ',
69
69
  languageAnalysisNoLanguage:
70
- 'We cannot detect a project, use --f <path> to specify a file or folder to analyze.',
70
+ 'We cannot detect a project, use -f <path> to specify a file or folder to analyze.',
71
71
  languageAnalysisNoLanguageHelpLine: `${chalk.bold(
72
72
  'contrast audit --help'
73
73
  )} for more information.`,
@@ -148,10 +148,15 @@ const en_locales = () => {
148
148
  '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
149
  constantsCount: 'The number of CVEs that must be exceeded to fail a build',
150
150
  constantsHeader: 'CodeSec by Contrast Security',
151
+ configHeader2: 'Config options',
152
+ clearHeader: '-c, --clear',
153
+ clearContent: 'Removes stored credentials',
151
154
  constantsPrerequisitesContentScanLanguages:
152
155
  'Java, Javascript and .NET supported',
153
156
  constantsContrastContent:
154
- "Use the 'contrast' command for fast and accurate security analysis of your applications and APIs (Java, JavaScript and .NET ) as well as serverless functions (AWS lambda, Java and Python).",
157
+ 'Use the contrast command for fast and accurate security analysis of your applications, APIs, serverless functions, and libraries.',
158
+ constantsContrastCategories:
159
+ '\n Code: Java, .NET, .NET Core, JavaScript\n Serverless: AWS Lambda - Java, Python\n Libraries: Java, .NET, Node, Ruby, Python, Go, PHP\n',
155
160
  constantsUsageGuideContentRecommendation:
156
161
  'Our recommendation is that this is invoked as part of a CI pipeline so that running the cli is automated as part of your build process.',
157
162
  constantsPrerequisitesHeader: 'Pre-requisites',
@@ -282,12 +287,17 @@ const en_locales = () => {
282
287
  'We only accept the following file types: \nJava - .jar, .war \nJavaScript - .js or .zip files',
283
288
  helpAuthSummary:
284
289
  'Authenticate Contrast using your Github or Google account',
285
- helpScanSummary: 'Perform static analysis on binaries / code artifacts',
286
- helpLambdaSummary: 'Perform scan on AWS Lambda functions',
290
+ helpAuditSummary:
291
+ 'Searches for a suitable file in the working directory to perform a security audit of dependencies and returns the results. [Contrast audit --help (for options).]',
292
+ helpScanSummary:
293
+ 'Searches for a .jar, .war, .js, or .zip file in the working directory, uploads files for analysis, and returns the results. [For further help/options, enter scan --help]',
294
+ helpLambdaSummary:
295
+ 'Performs a static security scan on an AWS lambda function. lambda --help (for options)',
287
296
  helpVersionSummary: 'Displays version of Contrast CLI',
288
297
  helpConfigSummary: 'Displays stored credentials',
289
298
  helpSummary: 'Displays usage guide',
290
299
  authName: 'auth',
300
+ auditName: 'audit',
291
301
  scanName: 'scan',
292
302
  lambdaName: 'lambda',
293
303
  versionName: 'version',
@@ -305,8 +315,7 @@ const en_locales = () => {
305
315
  scanOptionsVerboseSummary: ' Returns extended information to the terminal.',
306
316
  authSuccessMessage: 'Authentication successful',
307
317
  runAuthSuccessMessage:
308
- "Now you can use Contrast CLI \nRun 'contrast scan' on your file \n" +
309
- "or 'contrast help' to learn more about the capabilities.",
318
+ "Now you can use CodeSec by Contrast \nRun: \n'contrast scan' on your file \n'contrast audit' on a file or directory,\n'contrast lambda' on an AWS function.\nor 'contrast help' to learn more about the capabilities.",
310
319
  authWaitingMessage: 'Waiting for auth...',
311
320
  authTimedOutMessage: 'Auth Timed out, try again',
312
321
  zipErrorScan:
@@ -334,7 +343,7 @@ const en_locales = () => {
334
343
  'Supported runtimes: Java & Python',
335
344
  lambdaPrerequisitesContentLambdaDescriptionTitle: 'AWS Requirements\n',
336
345
  lambdaPrerequisitesContentLambdaDescription:
337
- 'Make sure you have the AWS credentials configured on your local environment. \nYou need the following AWS permissions configured on your IAM user:\n - Lambda: GetFunction, GetLayerVersionֿ\n - IAM: GetRolePolicy, GetPolicy, GetPolicyVersion, ListRolePolicies, ListAttachedRolePolicies',
346
+ 'Make sure you have the AWS credentials configured on your local environment. \nYou need the following AWS permissions configured on your IAM user:\n - Lambda: GetFunction, GetLayerVersion, ListFunctions\n - IAM: GetRolePolicy, GetPolicy, GetPolicyVersion, ListRolePolicies, ListAttachedRolePolicies',
338
347
  scanFileNameOption: '-f, --file',
339
348
  lambdaFunctionNameOption: '-f, --function-name',
340
349
  lambdaListFunctionsOption: '-l, --list-functions',
package/src/constants.js CHANGED
@@ -213,7 +213,7 @@ const auditOptionDefinitions = [
213
213
  {
214
214
  name: 'file',
215
215
  alias: 'f',
216
- defaultValue: process.cwd(),
216
+ defaultValue: process.cwd().concat('/'),
217
217
  description:
218
218
  '{bold ' +
219
219
  i18n.__('constantsOptional') +
@@ -347,7 +347,10 @@ const auditOptionDefinitions = [
347
347
  const mainUsageGuide = commandLineUsage([
348
348
  {
349
349
  header: i18n.__('constantsHeader'),
350
- content: [i18n.__('constantsContrastContent')]
350
+ content: [
351
+ i18n.__('constantsContrastContent'),
352
+ i18n.__('constantsContrastCategories')
353
+ ]
351
354
  },
352
355
  {
353
356
  header: i18n.__('constantsUsage'),
@@ -359,6 +362,7 @@ const mainUsageGuide = commandLineUsage([
359
362
  { name: i18n.__('authName'), summary: i18n.__('helpAuthSummary') },
360
363
  { name: i18n.__('scanName'), summary: i18n.__('helpScanSummary') },
361
364
  { name: i18n.__('lambdaName'), summary: i18n.__('helpLambdaSummary') },
365
+ { name: i18n.__('auditName'), summary: i18n.__('helpAuditSummary') },
362
366
  { name: i18n.__('versionName'), summary: i18n.__('helpVersionSummary') },
363
367
  { name: i18n.__('configName'), summary: i18n.__('helpConfigSummary') },
364
368
  { name: i18n.__('helpName'), summary: i18n.__('helpSummary') }
@@ -367,6 +371,12 @@ const mainUsageGuide = commandLineUsage([
367
371
  {
368
372
  content:
369
373
  '{underline https://developer.contrastsecurity.com/} \n For technical support head to {underline https://support.contrastsecurity.com}'
374
+ },
375
+ {
376
+ header: i18n.__('configHeader2'),
377
+ content: [
378
+ { name: i18n.__('clearHeader'), summary: i18n.__('clearContent') }
379
+ ]
370
380
  }
371
381
  ])
372
382
 
@@ -5,6 +5,9 @@ const formatMessage = require('../common/formatMessage')
5
5
  const jsAnalysis = async (config, languageFiles) => {
6
6
  checkForCorrectFiles(languageFiles)
7
7
 
8
+ if (!config.file.endsWith('/')) {
9
+ config.file = config.file.concat('/')
10
+ }
8
11
  return buildNodeTree(config, languageFiles.JAVASCRIPT)
9
12
  }
10
13
  const buildNodeTree = async (config, files) => {
@@ -1,6 +1,7 @@
1
1
  const i18n = require('i18n')
2
2
  const fileFinder = require('./fileUtils')
3
3
  const rootFile = require('../audit/languageAnalysisEngine/getProjectRootFilenames')
4
+ const path = require('path')
4
5
 
5
6
  const autoDetectFileAndLanguage = async configToUse => {
6
7
  const entries = await fileFinder.findFile()
@@ -27,16 +28,10 @@ const autoDetectFileAndLanguage = async configToUse => {
27
28
  }
28
29
  }
29
30
 
30
- const autoDetectAuditFilesAndLanguages = async file => {
31
- const filePath = file
31
+ const autoDetectAuditFilesAndLanguages = async filePath => {
32
32
  let languagesFound = []
33
33
 
34
- if (filePath) {
35
- rootFile.getProjectRootFilenames(filePath)
36
- console.log(i18n.__('searchingAuditFileDirectory', filePath))
37
- } else {
38
- console.log(i18n.__('searchingAuditFileDirectory', process.cwd()))
39
- }
34
+ console.log(i18n.__('searchingAuditFileDirectory', filePath))
40
35
 
41
36
  await fileFinder.findFilesJava(languagesFound, filePath)
42
37
  await fileFinder.findFilesJavascript(languagesFound, filePath)
@@ -46,13 +41,11 @@ const autoDetectAuditFilesAndLanguages = async file => {
46
41
  await fileFinder.findFilesRuby(languagesFound, filePath)
47
42
  await fileFinder.findFilesDotNet(languagesFound, filePath)
48
43
 
49
- if (languagesFound.length <= 1) {
44
+ if (languagesFound) {
50
45
  return languagesFound
51
- } else {
52
- console.log(
53
- 'found multiple languages, please specify one using --file to run SCA audit'
54
- )
55
46
  }
47
+
48
+ return []
56
49
  }
57
50
 
58
51
  const hasWhiteSpace = s => {
@@ -20,7 +20,7 @@ const handleResponseErrors = (res, api) => {
20
20
  } else if (res.statusCode === 412) {
21
21
  maxAppError()
22
22
  } else {
23
- genericError()
23
+ genericError(res)
24
24
  }
25
25
  }
26
26