@contrast/contrast 1.0.7 → 1.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/audit/autodetection/autoDetectLanguage.js +3 -3
- package/dist/audit/catalogueApplication/catalogueApplication.js +23 -5
- package/dist/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +5 -5
- package/dist/audit/languageAnalysisEngine/getProjectRootFilenames.js +9 -9
- package/dist/audit/languageAnalysisEngine/index.js +2 -2
- package/dist/audit/languageAnalysisEngine/languageAnalysisFactory.js +5 -28
- package/dist/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +11 -4
- package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +39 -13
- package/dist/audit/languageAnalysisEngine/report/models/reportListModel.js +2 -1
- package/dist/audit/languageAnalysisEngine/report/models/severityCountModel.js +3 -0
- package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +35 -14
- package/dist/audit/languageAnalysisEngine/report/utils/reportUtils.js +3 -3
- package/dist/audit/save.js +29 -0
- package/dist/commands/audit/auditController.js +21 -5
- package/dist/commands/audit/help.js +24 -1
- package/dist/commands/audit/processAudit.js +7 -1
- package/dist/commands/audit/saveFile.js +7 -3
- package/dist/commands/scan/sca/scaAnalysis.js +31 -10
- package/dist/common/HTTPClient.js +6 -0
- package/dist/common/versionChecker.js +19 -4
- package/dist/constants/constants.js +1 -1
- package/dist/constants/locales.js +12 -11
- package/dist/constants.js +9 -4
- package/dist/index.js +4 -3
- package/dist/sbom/generateSbom.js +4 -3
- package/dist/scaAnalysis/common/formatMessage.js +26 -5
- package/dist/scaAnalysis/common/treeUpload.js +0 -1
- package/dist/scaAnalysis/go/goReadDepFile.js +1 -3
- package/dist/scaAnalysis/java/analysis.js +5 -5
- package/dist/scaAnalysis/javascript/analysis.js +110 -0
- package/dist/scaAnalysis/javascript/index.js +41 -0
- package/dist/scaAnalysis/php/analysis.js +89 -0
- package/dist/scaAnalysis/php/index.js +10 -0
- package/dist/scaAnalysis/python/analysis.js +8 -7
- package/dist/scaAnalysis/ruby/analysis.js +8 -8
- package/dist/scaAnalysis/ruby/index.js +2 -2
- package/dist/scan/autoDetection.js +4 -4
- package/dist/scan/fileUtils.js +13 -2
- package/dist/utils/filterProjectPath.js +7 -2
- package/package.json +3 -3
- package/src/audit/autodetection/autoDetectLanguage.ts +3 -3
- package/src/audit/catalogueApplication/catalogueApplication.js +28 -6
- package/src/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +5 -5
- package/src/audit/languageAnalysisEngine/getProjectRootFilenames.js +11 -11
- package/src/audit/languageAnalysisEngine/index.js +2 -2
- package/src/audit/languageAnalysisEngine/languageAnalysisFactory.js +4 -32
- package/src/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +20 -19
- package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.ts +67 -17
- package/src/audit/languageAnalysisEngine/report/models/reportListModel.ts +4 -1
- package/src/audit/languageAnalysisEngine/report/models/severityCountModel.ts +4 -0
- package/src/audit/languageAnalysisEngine/report/reportingFeature.ts +49 -17
- package/src/audit/languageAnalysisEngine/report/utils/reportUtils.ts +1 -1
- package/src/audit/save.js +32 -0
- package/src/commands/audit/auditController.ts +22 -13
- package/src/commands/audit/help.ts +24 -1
- package/src/commands/audit/processAudit.ts +6 -3
- package/src/commands/audit/saveFile.ts +5 -1
- package/src/commands/scan/sca/scaAnalysis.js +53 -22
- package/src/common/HTTPClient.js +7 -0
- package/src/common/versionChecker.ts +23 -4
- package/src/constants/constants.js +1 -1
- package/src/constants/locales.js +12 -11
- package/src/constants.js +9 -4
- package/src/index.ts +5 -3
- package/src/sbom/generateSbom.ts +1 -1
- package/src/scaAnalysis/common/formatMessage.js +27 -5
- package/src/scaAnalysis/common/treeUpload.js +0 -1
- package/src/scaAnalysis/go/goReadDepFile.js +1 -3
- package/src/scaAnalysis/java/analysis.js +5 -5
- package/src/scaAnalysis/javascript/analysis.js +127 -0
- package/src/scaAnalysis/javascript/index.js +56 -0
- package/src/scaAnalysis/php/analysis.js +98 -0
- package/src/scaAnalysis/php/index.js +11 -0
- package/src/scaAnalysis/python/analysis.js +8 -7
- package/src/scaAnalysis/ruby/analysis.js +8 -8
- package/src/scaAnalysis/ruby/index.js +2 -2
- package/src/scan/autoDetection.js +4 -4
- package/src/scan/fileUtils.js +13 -2
- package/src/utils/filterProjectPath.js +6 -2
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const multiReplace = require('string-multiple-replace');
|
|
3
3
|
const fs = require('fs');
|
|
4
|
-
const readAndParseProjectFile =
|
|
5
|
-
const filePath = filePathForWindows(
|
|
4
|
+
const readAndParseProjectFile = file => {
|
|
5
|
+
const filePath = filePathForWindows(file + '/Pipfile');
|
|
6
6
|
const pipFile = fs.readFileSync(filePath, 'utf8');
|
|
7
7
|
const matcherObj = { '"': '' };
|
|
8
8
|
const sequencer = ['"'];
|
|
@@ -10,18 +10,19 @@ const readAndParseProjectFile = projectPath => {
|
|
|
10
10
|
const pythonArray = parsedPipfile.split('\n');
|
|
11
11
|
return pythonArray.filter(element => element !== '' && !element.includes('#'));
|
|
12
12
|
};
|
|
13
|
-
const readAndParseLockFile =
|
|
14
|
-
const filePath = filePathForWindows(
|
|
13
|
+
const readAndParseLockFile = file => {
|
|
14
|
+
const filePath = filePathForWindows(file + '/Pipfile.lock');
|
|
15
15
|
const lockFile = fs.readFileSync(filePath, 'utf8');
|
|
16
16
|
let parsedPipLock = JSON.parse(lockFile);
|
|
17
17
|
parsedPipLock['defaults'] = parsedPipLock['default'];
|
|
18
|
+
delete parsedPipLock['default'];
|
|
18
19
|
return parsedPipLock;
|
|
19
20
|
};
|
|
20
21
|
const getPythonDeps = config => {
|
|
21
22
|
try {
|
|
22
|
-
const parseProject = readAndParseProjectFile(config.
|
|
23
|
-
const parsePip = readAndParseLockFile(config.
|
|
24
|
-
return { pipfileLock:
|
|
23
|
+
const parseProject = readAndParseProjectFile(config.file);
|
|
24
|
+
const parsePip = readAndParseLockFile(config.file);
|
|
25
|
+
return { pipfileLock: parsePip, pipfilDependanceies: parseProject };
|
|
25
26
|
}
|
|
26
27
|
catch (err) {
|
|
27
28
|
console.log(err.message.toString());
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const fs = require('fs');
|
|
3
|
-
const readAndParseGemfile =
|
|
4
|
-
const fileName = filePathForWindows(
|
|
3
|
+
const readAndParseGemfile = file => {
|
|
4
|
+
const fileName = filePathForWindows(file + '/Gemfile');
|
|
5
5
|
const gemFile = fs.readFileSync(fileName, 'utf8');
|
|
6
6
|
const rubyArray = gemFile.split('\n');
|
|
7
7
|
let filteredRubyDep = rubyArray.filter(element => {
|
|
@@ -14,8 +14,8 @@ const readAndParseGemfile = projectPath => {
|
|
|
14
14
|
}
|
|
15
15
|
return filteredRubyDep;
|
|
16
16
|
};
|
|
17
|
-
const readAndParseGemLockFile =
|
|
18
|
-
const fileName = filePathForWindows(
|
|
17
|
+
const readAndParseGemLockFile = file => {
|
|
18
|
+
const fileName = filePathForWindows(file + '/Gemfile.lock');
|
|
19
19
|
const lockFile = fs.readFileSync(fileName, 'utf8');
|
|
20
20
|
const dependencyRegEx = /^\s*([A-Za-z0-9.!@#$%\-^&*_+]*)\s*(\((.*?)\))/;
|
|
21
21
|
const lines = lockFile.split('\n');
|
|
@@ -26,7 +26,7 @@ const readAndParseGemLockFile = projectPath => {
|
|
|
26
26
|
};
|
|
27
27
|
};
|
|
28
28
|
const nonDependencyKeys = (line, sourceObject) => {
|
|
29
|
-
const GEMFILE_KEY_VALUE = /^\s*([^:(]*)\s
|
|
29
|
+
const GEMFILE_KEY_VALUE = /^\s*([^:(]*)\s*\:*\s*(.*)/;
|
|
30
30
|
let parts = GEMFILE_KEY_VALUE.exec(line);
|
|
31
31
|
let key = parts[1].trim();
|
|
32
32
|
let value = parts[2] || '';
|
|
@@ -164,7 +164,7 @@ const getSourceArray = (lines, dependencyRegEx) => {
|
|
|
164
164
|
}
|
|
165
165
|
if ((currentWS === 4 && nexlineWS === 4) ||
|
|
166
166
|
(currentWS === 6 && nexlineWS === 4) ||
|
|
167
|
-
nexlineWS
|
|
167
|
+
nexlineWS == '') {
|
|
168
168
|
let newObj = {};
|
|
169
169
|
newObj = JSON.parse(JSON.stringify(sourceObject));
|
|
170
170
|
sources.push(newObj);
|
|
@@ -192,8 +192,8 @@ const buildSourceDependencyWithVersion = (whitespaceRegx, dependencyRegEx, line,
|
|
|
192
192
|
};
|
|
193
193
|
const getRubyDeps = config => {
|
|
194
194
|
try {
|
|
195
|
-
const parsedGem = readAndParseGemfile(config.
|
|
196
|
-
const parsedLock = readAndParseGemLockFile(config.
|
|
195
|
+
const parsedGem = readAndParseGemfile(config.file);
|
|
196
|
+
const parsedLock = readAndParseGemLockFile(config.file);
|
|
197
197
|
return { gemfilesDependanceies: parsedGem, gemfileLock: parsedLock };
|
|
198
198
|
}
|
|
199
199
|
catch (err) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const
|
|
2
|
+
const analysis = require('./analysis');
|
|
3
3
|
const { createRubyTSMessage } = require('../common/formatMessage');
|
|
4
4
|
const rubyAnalysis = (config, languageFiles) => {
|
|
5
|
-
const rubyDeps = getRubyDeps(config, languageFiles.RUBY);
|
|
5
|
+
const rubyDeps = analysis.getRubyDeps(config, languageFiles.RUBY);
|
|
6
6
|
return createRubyTSMessage(rubyDeps);
|
|
7
7
|
};
|
|
8
8
|
module.exports = {
|
|
@@ -37,14 +37,14 @@ const autoDetectAuditFilesAndLanguages = async () => {
|
|
|
37
37
|
return languagesFound;
|
|
38
38
|
}
|
|
39
39
|
else {
|
|
40
|
-
console.log('found multiple languages, please specify one using --file to run SCA
|
|
40
|
+
console.log('found multiple languages, please specify one using --file to run SCA audit');
|
|
41
41
|
}
|
|
42
42
|
};
|
|
43
|
-
const manualDetectAuditFilesAndLanguages =
|
|
44
|
-
let projectRootFilenames = rootFile.getProjectRootFilenames(
|
|
43
|
+
const manualDetectAuditFilesAndLanguages = file => {
|
|
44
|
+
let projectRootFilenames = rootFile.getProjectRootFilenames(file);
|
|
45
45
|
let identifiedLanguages = languageResolver.deduceLanguageScaAnalysis(projectRootFilenames);
|
|
46
46
|
if (Object.keys(identifiedLanguages).length === 0) {
|
|
47
|
-
console.log(i18n.__('languageAnalysisNoLanguage',
|
|
47
|
+
console.log(i18n.__('languageAnalysisNoLanguage', file));
|
|
48
48
|
return [];
|
|
49
49
|
}
|
|
50
50
|
return [identifiedLanguages];
|
package/dist/scan/fileUtils.js
CHANGED
|
@@ -22,7 +22,7 @@ const findFilesJava = async (languagesFound) => {
|
|
|
22
22
|
return languagesFound;
|
|
23
23
|
};
|
|
24
24
|
const findFilesJavascript = async (languagesFound) => {
|
|
25
|
-
const result = await fg(['**/package.json', '**/yarn.lock', '**/package
|
|
25
|
+
const result = await fg(['**/package.json', '**/yarn.lock', '**/package-lock.json'], {
|
|
26
26
|
dot: false,
|
|
27
27
|
deep: 1,
|
|
28
28
|
onlyFiles: true
|
|
@@ -92,7 +92,18 @@ const fileExists = path => {
|
|
|
92
92
|
};
|
|
93
93
|
const fileIsEmpty = path => {
|
|
94
94
|
if (fileExists(path) && checkFilePermissions(path)) {
|
|
95
|
-
|
|
95
|
+
try {
|
|
96
|
+
return fs.readFileSync(path).length === 0;
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
if (e.message.toString().includes('illegal operation on a directory, read')) {
|
|
100
|
+
console.log('file provided cannot be a directory');
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
console.log(e.message.toString());
|
|
104
|
+
}
|
|
105
|
+
process.exit(0);
|
|
106
|
+
}
|
|
96
107
|
}
|
|
97
108
|
return false;
|
|
98
109
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const path = require('path');
|
|
3
|
+
const child_process = require('child_process');
|
|
3
4
|
function resolveFilePath(filepath) {
|
|
4
5
|
if (filepath[0] === '~') {
|
|
5
6
|
return path.join(process.env.HOME, filepath.slice(1));
|
|
@@ -7,11 +8,15 @@ function resolveFilePath(filepath) {
|
|
|
7
8
|
return filepath;
|
|
8
9
|
}
|
|
9
10
|
const returnProjectPath = () => {
|
|
10
|
-
if (process.
|
|
11
|
+
if (process.platform == 'win32') {
|
|
12
|
+
let winPath = child_process.execSync('cd').toString();
|
|
13
|
+
return winPath.replace(/\//g, '\\').trim();
|
|
14
|
+
}
|
|
15
|
+
else if (process.env.PWD !== (undefined || null || 'undefined')) {
|
|
11
16
|
return process.env.PWD;
|
|
12
17
|
}
|
|
13
18
|
else {
|
|
14
|
-
return process.argv[process.argv.indexOf('--
|
|
19
|
+
return process.argv[process.argv.indexOf('--file') + 1];
|
|
15
20
|
}
|
|
16
21
|
};
|
|
17
22
|
module.exports = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contrast/contrast",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"description": "Contrast Security's command line tool",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
"test": "jest --testPathIgnorePatterns=./test-integration/",
|
|
24
24
|
"test-int": "jest ./test-integration/",
|
|
25
25
|
"test-int-scan": "jest ./test-integration/scan",
|
|
26
|
-
"test-int-audit": "jest ./test-integration/audit",
|
|
26
|
+
"test-int-audit": "jest ./test-integration/audit/audit.spec.js",
|
|
27
|
+
"test-int-audit-experimental": "jest ./test-integration/audit/audit-experimental.spec.js",
|
|
27
28
|
"format": "prettier --write \"**/*.{ts,tsx,js,json,md,yml}\" .eslintrc.*",
|
|
28
29
|
"check-format": "prettier --check \"**/*.{ts,tsx,js,json,md,yml}\" .eslintrc.*",
|
|
29
30
|
"coverage-local": "nyc --reporter=text mocha './test/**/*.spec.js'",
|
|
@@ -53,7 +54,6 @@
|
|
|
53
54
|
"fast-glob": "^3.2.11",
|
|
54
55
|
"i18n": "^0.14.2",
|
|
55
56
|
"js-yaml": "^4.1.0",
|
|
56
|
-
"latest-version": "5.1.0",
|
|
57
57
|
"lodash": "^4.17.21",
|
|
58
58
|
"log-symbols": "^4.1.0",
|
|
59
59
|
"open": "^8.4.0",
|
|
@@ -8,8 +8,8 @@ import {
|
|
|
8
8
|
import { getProjectRootFilenames } from '../languageAnalysisEngine/getProjectRootFilenames'
|
|
9
9
|
|
|
10
10
|
export function identifyLanguages(config: any) {
|
|
11
|
-
const {
|
|
12
|
-
const projectRootFilenames = getProjectRootFilenames(
|
|
11
|
+
const { file } = config
|
|
12
|
+
const projectRootFilenames = getProjectRootFilenames(file)
|
|
13
13
|
|
|
14
14
|
const identifiedLanguages = projectRootFilenames.reduce(
|
|
15
15
|
(accumulator: any, filename: string) => {
|
|
@@ -20,7 +20,7 @@ export function identifyLanguages(config: any) {
|
|
|
20
20
|
)
|
|
21
21
|
|
|
22
22
|
if (Object.keys(identifiedLanguages).length === 0) {
|
|
23
|
-
throw new Error(i18n.__('languageAnalysisNoLanguage',
|
|
23
|
+
throw new Error(i18n.__('languageAnalysisNoLanguage', file))
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
return reduceIdentifiedLanguages(identifiedLanguages)
|
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
const i18n = require('i18n')
|
|
2
1
|
const { getHttpClient, handleResponseErrors } = require('../../utils/commonApi')
|
|
3
2
|
|
|
4
|
-
const displaySuccessMessage = () => {
|
|
5
|
-
console.log(i18n.__('catalogueSuccessCommand'))
|
|
6
|
-
}
|
|
7
|
-
|
|
8
3
|
const catalogueApplication = async config => {
|
|
9
4
|
const client = getHttpClient(config)
|
|
10
5
|
let appId
|
|
@@ -14,6 +9,8 @@ const catalogueApplication = async config => {
|
|
|
14
9
|
if (res.statusCode === 201) {
|
|
15
10
|
//displaySuccessMessage(config, res.body.application.app_id)
|
|
16
11
|
appId = res.body.application.app_id
|
|
12
|
+
} else if (doesMessagesContainAppId(res)) {
|
|
13
|
+
appId = tryRetrieveAppIdFromMessages(res.body.messages)
|
|
17
14
|
} else {
|
|
18
15
|
handleResponseErrors(res, 'catalogue')
|
|
19
16
|
}
|
|
@@ -24,6 +21,31 @@ const catalogueApplication = async config => {
|
|
|
24
21
|
return appId
|
|
25
22
|
}
|
|
26
23
|
|
|
24
|
+
const doesMessagesContainAppId = res => {
|
|
25
|
+
const regex = /(Application ID =)/
|
|
26
|
+
if (
|
|
27
|
+
res.statusCode === 400 &&
|
|
28
|
+
res.body.messages.filter(message => regex.exec(message))[0]
|
|
29
|
+
) {
|
|
30
|
+
return true
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return false
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const tryRetrieveAppIdFromMessages = messages => {
|
|
37
|
+
let appId
|
|
38
|
+
messages.forEach(message => {
|
|
39
|
+
if (message.includes('Application ID')) {
|
|
40
|
+
appId = message.split('=')[1].replace(/\s+/g, '')
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
return appId
|
|
45
|
+
}
|
|
46
|
+
|
|
27
47
|
module.exports = {
|
|
28
|
-
catalogueApplication: catalogueApplication
|
|
48
|
+
catalogueApplication: catalogueApplication,
|
|
49
|
+
doesMessagesContainAppId,
|
|
50
|
+
tryRetrieveAppIdFromMessages
|
|
29
51
|
}
|
|
@@ -5,15 +5,15 @@ const path = require('path')
|
|
|
5
5
|
* language, project file name and paths
|
|
6
6
|
*/
|
|
7
7
|
module.exports = exports = (analysis, next) => {
|
|
8
|
-
const {
|
|
8
|
+
const { file, languageAnalysis } = analysis
|
|
9
9
|
languageAnalysis.identifiedLanguageInfo = getIdentifiedLanguageInfo(
|
|
10
|
-
|
|
10
|
+
file,
|
|
11
11
|
languageAnalysis.identifiedLanguages
|
|
12
12
|
)
|
|
13
13
|
next()
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
const getIdentifiedLanguageInfo = (
|
|
16
|
+
const getIdentifiedLanguageInfo = (file, identifiedLanguages) => {
|
|
17
17
|
const [language] = Object.keys(identifiedLanguages)
|
|
18
18
|
const {
|
|
19
19
|
projectFilenames: [projectFilename],
|
|
@@ -23,14 +23,14 @@ const getIdentifiedLanguageInfo = (projectPath, identifiedLanguages) => {
|
|
|
23
23
|
let identifiedLanguageInfo = {
|
|
24
24
|
language,
|
|
25
25
|
projectFilename,
|
|
26
|
-
projectFilePath: path.join(
|
|
26
|
+
projectFilePath: path.join(file, projectFilename)
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
if (lockFilename) {
|
|
30
30
|
identifiedLanguageInfo = {
|
|
31
31
|
...identifiedLanguageInfo,
|
|
32
32
|
lockFilename,
|
|
33
|
-
lockFilePath: path.join(
|
|
33
|
+
lockFilePath: path.join(file, lockFilename)
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
|
|
@@ -9,21 +9,21 @@ const i18n = require('i18n')
|
|
|
9
9
|
* Will fail and throw for a manner of reasons when doing file/directory
|
|
10
10
|
* inspection.
|
|
11
11
|
*
|
|
12
|
-
* @param {string}
|
|
12
|
+
* @param {string} file - The path to a projects root directory or a
|
|
13
13
|
* specific project file
|
|
14
14
|
*
|
|
15
15
|
* @return {string[]} List of filenames associated with a projects root
|
|
16
16
|
* directory or the name of the specific project file if that was provided to
|
|
17
|
-
* the '
|
|
17
|
+
* the 'file' parameter
|
|
18
18
|
*
|
|
19
19
|
* @throws {Error} If the project path doesn't exist
|
|
20
20
|
* @throws {Error} If the project path information can't be collected
|
|
21
21
|
* @throws {Error} If a non-file or non-directory inspected
|
|
22
22
|
*/
|
|
23
23
|
module.exports = exports = (analysis, next) => {
|
|
24
|
-
const {
|
|
24
|
+
const { file, languageAnalysis } = analysis
|
|
25
25
|
try {
|
|
26
|
-
languageAnalysis.projectRootFilenames = getProjectRootFilenames(
|
|
26
|
+
languageAnalysis.projectRootFilenames = getProjectRootFilenames(file)
|
|
27
27
|
} catch (err) {
|
|
28
28
|
next(err)
|
|
29
29
|
return
|
|
@@ -31,13 +31,13 @@ module.exports = exports = (analysis, next) => {
|
|
|
31
31
|
next()
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
const getProjectRootFilenames =
|
|
34
|
+
const getProjectRootFilenames = file => {
|
|
35
35
|
let projectStats = null
|
|
36
36
|
try {
|
|
37
|
-
projectStats = fs.statSync(
|
|
37
|
+
projectStats = fs.statSync(file)
|
|
38
38
|
} catch (err) {
|
|
39
39
|
throw new Error(
|
|
40
|
-
i18n.__('languageAnalysisProjectRootFileNameFailure',
|
|
40
|
+
i18n.__('languageAnalysisProjectRootFileNameFailure', file) +
|
|
41
41
|
`${err.message}`
|
|
42
42
|
)
|
|
43
43
|
}
|
|
@@ -45,10 +45,10 @@ const getProjectRootFilenames = projectPath => {
|
|
|
45
45
|
// Return the contents of a directory...
|
|
46
46
|
if (projectStats.isDirectory()) {
|
|
47
47
|
try {
|
|
48
|
-
return fs.readdirSync(
|
|
48
|
+
return fs.readdirSync(file)
|
|
49
49
|
} catch (err) {
|
|
50
50
|
throw new Error(
|
|
51
|
-
i18n.__('languageAnalysisProjectRootFileNameReadError',
|
|
51
|
+
i18n.__('languageAnalysisProjectRootFileNameReadError', file) +
|
|
52
52
|
`${err.message}`
|
|
53
53
|
)
|
|
54
54
|
}
|
|
@@ -57,14 +57,14 @@ const getProjectRootFilenames = projectPath => {
|
|
|
57
57
|
// If we are working with a file return it in a list as we do when we work
|
|
58
58
|
// with a directory...
|
|
59
59
|
if (projectStats.isFile()) {
|
|
60
|
-
return [path.basename(
|
|
60
|
+
return [path.basename(file)]
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
// Error out if we are working with something like a socket file or some
|
|
64
64
|
// other craziness...
|
|
65
65
|
throw new Error(
|
|
66
66
|
i18n.__('languageAnalysisProjectRootFileNameMissingError'),
|
|
67
|
-
|
|
67
|
+
file
|
|
68
68
|
)
|
|
69
69
|
}
|
|
70
70
|
|
|
@@ -10,10 +10,10 @@ const checkIdentifiedLanguageHasLockFile = require('./checkIdentifiedLanguageHas
|
|
|
10
10
|
const getIdentifiedLanguageInfo = require('./getIdentifiedLanguageInfo')
|
|
11
11
|
const { libraryAnalysisError } = require('../../common/errorHandling')
|
|
12
12
|
|
|
13
|
-
module.exports = exports = (
|
|
13
|
+
module.exports = exports = (file, callback, appId, config) => {
|
|
14
14
|
// Create an analysis engine to identify the project language
|
|
15
15
|
const ae = new AnalysisEngine({
|
|
16
|
-
|
|
16
|
+
file,
|
|
17
17
|
appId,
|
|
18
18
|
languageAnalysis: { appId: appId },
|
|
19
19
|
config
|
|
@@ -11,17 +11,13 @@ const phpAE = require('../phpAnalysisEngine')
|
|
|
11
11
|
const goAE = require('../goAnalysisEngine')
|
|
12
12
|
const { vulnerabilityReport } = require('./report/reportingFeature')
|
|
13
13
|
const { newSendSnapShot } = require('../languageAnalysisEngine/sendSnapshot')
|
|
14
|
-
const fs = require('fs')
|
|
15
|
-
const chalk = require('chalk')
|
|
16
|
-
const saveFile = require('../../commands/audit/saveFile').default
|
|
17
|
-
const generateSbom = require('../../sbom/generateSbom').default
|
|
18
14
|
const {
|
|
19
|
-
failSpinner,
|
|
20
15
|
returnOra,
|
|
21
16
|
startSpinner,
|
|
22
17
|
succeedSpinner
|
|
23
18
|
} = require('../../utils/oraWrapper')
|
|
24
19
|
const { pollForSnapshotCompletition } = require('./sendSnapshot')
|
|
20
|
+
const auditSave = require('../save')
|
|
25
21
|
|
|
26
22
|
module.exports = exports = (err, analysis) => {
|
|
27
23
|
const { identifiedLanguageInfo } = analysis.languageAnalysis
|
|
@@ -57,17 +53,17 @@ module.exports = exports = (err, analysis) => {
|
|
|
57
53
|
const snapshotResponse = await newSendSnapShot(analysis, catalogueAppId)
|
|
58
54
|
|
|
59
55
|
//poll for completion
|
|
60
|
-
|
|
56
|
+
await pollForSnapshotCompletition(
|
|
61
57
|
analysis.config,
|
|
62
58
|
snapshotResponse.id,
|
|
63
59
|
reportSpinner
|
|
64
60
|
)
|
|
65
|
-
succeedSpinner(reportSpinner, '
|
|
61
|
+
succeedSpinner(reportSpinner, i18n.__('auditSCAAnalysisComplete'))
|
|
66
62
|
|
|
67
63
|
await vulnerabilityReport(analysis, catalogueAppId, snapshotResponse.id)
|
|
68
64
|
|
|
69
65
|
//should be moved to processAudit.ts once promises implemented
|
|
70
|
-
await auditSave(config)
|
|
66
|
+
await auditSave.auditSave(config)
|
|
71
67
|
}
|
|
72
68
|
|
|
73
69
|
if (identifiedLanguageInfo.language === DOTNET) {
|
|
@@ -98,27 +94,3 @@ module.exports = exports = (err, analysis) => {
|
|
|
98
94
|
goAE(identifiedLanguageInfo, analysis.config, langCallback)
|
|
99
95
|
}
|
|
100
96
|
}
|
|
101
|
-
|
|
102
|
-
async function auditSave(config) {
|
|
103
|
-
//should be moved to processAudit.ts once promises implemented
|
|
104
|
-
if (config.save) {
|
|
105
|
-
if (config.save.toLowerCase() === 'sbom') {
|
|
106
|
-
saveFile(config, await generateSbom(config))
|
|
107
|
-
|
|
108
|
-
const filename = `${config.applicationId}-sbom-cyclonedx.json`
|
|
109
|
-
if (fs.existsSync(filename)) {
|
|
110
|
-
console.log(i18n.__('auditSBOMSaveSuccess') + ` - ${filename}`)
|
|
111
|
-
} else {
|
|
112
|
-
console.log(
|
|
113
|
-
chalk.yellow.bold(
|
|
114
|
-
`\n Unable to save ${filename} Software Bill of Materials (SBOM)`
|
|
115
|
-
)
|
|
116
|
-
)
|
|
117
|
-
}
|
|
118
|
-
} else {
|
|
119
|
-
console.log(i18n.__('auditBadFiletypeSpecifiedForSave'))
|
|
120
|
-
}
|
|
121
|
-
} else if (config.save === null) {
|
|
122
|
-
console.log(i18n.__('auditNoFiletypeSpecifiedForSave'))
|
|
123
|
-
}
|
|
124
|
-
}
|
|
@@ -46,37 +46,38 @@ const deduceLanguageScaAnalysis = filenames => {
|
|
|
46
46
|
|
|
47
47
|
if (isNodeProjectFilename(filename)) {
|
|
48
48
|
deducedLanguages.push(filename)
|
|
49
|
-
language =
|
|
49
|
+
language = JAVASCRIPT
|
|
50
50
|
}
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
// if (isDotNetProjectFilename(filename)) {
|
|
53
53
|
// deducedLanguages.push({language: DOTNET, projectFilename: filename})
|
|
54
54
|
// }
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
if (isRubyProjectFilename(filename)) {
|
|
57
57
|
deducedLanguages.push(filename)
|
|
58
58
|
language = RUBY
|
|
59
59
|
}
|
|
60
|
-
|
|
60
|
+
|
|
61
61
|
if (isPythonProjectFilename(filename)) {
|
|
62
62
|
deducedLanguages.push(filename)
|
|
63
63
|
language = PYTHON
|
|
64
64
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
65
|
+
|
|
66
|
+
if (isPhpProjectFilename(filename)) {
|
|
67
|
+
deducedLanguages.push({ language: PHP, projectFilename: filename })
|
|
68
|
+
language = PHP
|
|
69
|
+
}
|
|
70
|
+
|
|
70
71
|
// // Check for lock filenames...
|
|
71
72
|
// if (isDotNetLockFilename(filename)) {
|
|
72
73
|
// deducedLanguages.push({language: DOTNET, lockFilename: filename})
|
|
73
74
|
// }
|
|
74
|
-
|
|
75
|
+
|
|
75
76
|
if (isNodeLockFilename(filename)) {
|
|
76
77
|
deducedLanguages.push(filename)
|
|
77
|
-
language =
|
|
78
|
+
language = JAVASCRIPT
|
|
78
79
|
}
|
|
79
|
-
|
|
80
|
+
|
|
80
81
|
// if (isRubyLockFilename(filename)) {
|
|
81
82
|
// deducedLanguages.push({language: RUBY, lockFilename: filename})
|
|
82
83
|
// }
|
|
@@ -85,11 +86,11 @@ const deduceLanguageScaAnalysis = filenames => {
|
|
|
85
86
|
// if (isPipfileLockLockFilename(filename)) {
|
|
86
87
|
// deducedLanguages.push({language: PYTHON, lockFilename: filename})
|
|
87
88
|
// }
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
89
|
+
|
|
90
|
+
if (isPhpLockFilename(filename)) {
|
|
91
|
+
deducedLanguages.push({ language: PHP, lockFilename: filename })
|
|
92
|
+
}
|
|
93
|
+
|
|
93
94
|
// go does not have a lockfile, it should have a go.mod file containing the modules
|
|
94
95
|
if (isGoProjectFilename(filename)) {
|
|
95
96
|
deducedLanguages.push({ language: GO, projectFilename: filename })
|
|
@@ -192,7 +193,7 @@ const reduceIdentifiedLanguages = identifiedLanguages =>
|
|
|
192
193
|
* specifies a specific language
|
|
193
194
|
*/
|
|
194
195
|
module.exports = exports = (analysis, next) => {
|
|
195
|
-
const {
|
|
196
|
+
const { file, languageAnalysis, config } = analysis
|
|
196
197
|
|
|
197
198
|
let identifiedLanguages = languageAnalysis.projectRootFilenames.reduce(
|
|
198
199
|
(accumulator, filename) => {
|
|
@@ -203,7 +204,7 @@ module.exports = exports = (analysis, next) => {
|
|
|
203
204
|
)
|
|
204
205
|
|
|
205
206
|
if (Object.keys(identifiedLanguages).length === 0) {
|
|
206
|
-
next(new Error(i18n.__('languageAnalysisNoLanguage',
|
|
207
|
+
next(new Error(i18n.__('languageAnalysisNoLanguage', file)))
|
|
207
208
|
return
|
|
208
209
|
}
|
|
209
210
|
|