2779 lines
104 KiB
JavaScript
2779 lines
104 KiB
JavaScript
"use strict";
|
|
exports.id = 741;
|
|
exports.ids = [741];
|
|
exports.modules = {
|
|
|
|
/***/ 80423:
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.convertLegacyTestResultToNew = void 0;
|
|
function convertVulnerabilities(vulns) {
|
|
const issuesData = {};
|
|
const issues = [];
|
|
vulns.forEach((vuln) => {
|
|
issuesData[vuln.id] = {
|
|
id: vuln.id,
|
|
severity: vuln.severity,
|
|
title: vuln.title,
|
|
};
|
|
issues.push({
|
|
pkgName: vuln.packageName,
|
|
pkgVersion: vuln.version,
|
|
issueId: vuln.id,
|
|
// TODO: add fixInfo when needed
|
|
fixInfo: {},
|
|
});
|
|
});
|
|
return { issuesData, issues };
|
|
}
|
|
function convertLegacyTestResultToNew(testResult) {
|
|
const { issues, issuesData } = convertVulnerabilities(testResult.vulnerabilities);
|
|
return {
|
|
issuesData,
|
|
issues,
|
|
remediation: testResult.remediation,
|
|
// TODO: grab this once Ecosystems flow starts sending back ScanResult
|
|
depGraphData: {},
|
|
};
|
|
}
|
|
exports.convertLegacyTestResultToNew = convertLegacyTestResultToNew;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 16898:
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.convertLegacyTestResultToScanResult = void 0;
|
|
function convertLegacyTestResultToScanResult(testResult) {
|
|
if (!testResult.packageManager) {
|
|
throw new Error('Only results with packageManagers are supported for conversion');
|
|
}
|
|
return {
|
|
identity: {
|
|
type: testResult.packageManager,
|
|
// this is because not all plugins send it back today, but we should always have it
|
|
targetFile: testResult.targetFile || testResult.displayTargetFile,
|
|
},
|
|
name: testResult.projectName,
|
|
// TODO: grab this once Ecosystems flow starts sending back ScanResult
|
|
facts: [],
|
|
policy: testResult.policy,
|
|
// TODO: grab this once Ecosystems flow starts sending back ScanResult
|
|
target: {},
|
|
};
|
|
}
|
|
exports.convertLegacyTestResultToScanResult = convertLegacyTestResultToScanResult;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 92730:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.convertLegacyTestResultToFixEntities = void 0;
|
|
const fs = __webpack_require__(35747);
|
|
const pathLib = __webpack_require__(85622);
|
|
const convert_legacy_test_result_to_new_1 = __webpack_require__(80423);
|
|
const convert_legacy_test_result_to_scan_result_1 = __webpack_require__(16898);
|
|
function convertLegacyTestResultToFixEntities(testResults, root, options) {
|
|
if (testResults instanceof Error) {
|
|
return [];
|
|
}
|
|
const oldResults = Array.isArray(testResults) ? testResults : [testResults];
|
|
return oldResults.map((res) => ({
|
|
options,
|
|
workspace: {
|
|
path: root,
|
|
readFile: async (path) => {
|
|
return fs.readFileSync(pathLib.resolve(root, path), 'utf8');
|
|
},
|
|
writeFile: async (path, content) => {
|
|
return fs.writeFileSync(pathLib.resolve(root, path), content, 'utf8');
|
|
},
|
|
},
|
|
scanResult: convert_legacy_test_result_to_scan_result_1.convertLegacyTestResultToScanResult(res),
|
|
testResult: convert_legacy_test_result_to_new_1.convertLegacyTestResultToNew(res),
|
|
}));
|
|
}
|
|
exports.convertLegacyTestResultToFixEntities = convertLegacyTestResultToFixEntities;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 79898:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.getDisplayPath = void 0;
|
|
const pathLib = __webpack_require__(85622);
|
|
const detect_1 = __webpack_require__(45318);
|
|
function getDisplayPath(path) {
|
|
if (!detect_1.isLocalFolder(path)) {
|
|
return path;
|
|
}
|
|
if (path === process.cwd()) {
|
|
return pathLib.parse(path).name;
|
|
}
|
|
return pathLib.relative(process.cwd(), path);
|
|
}
|
|
exports.getDisplayPath = getDisplayPath;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 73741:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
const Debug = __webpack_require__(15158);
|
|
const snykFix = __webpack_require__(53776);
|
|
const ora = __webpack_require__(63395);
|
|
const snyk = __webpack_require__(9146);
|
|
const analytics = __webpack_require__(82744);
|
|
const convert_legacy_tests_results_to_fix_entities_1 = __webpack_require__(92730);
|
|
const format_test_error_1 = __webpack_require__(68214);
|
|
const process_command_args_1 = __webpack_require__(52369);
|
|
const validate_credentials_1 = __webpack_require__(4593);
|
|
const validate_test_options_1 = __webpack_require__(83476);
|
|
const set_default_test_options_1 = __webpack_require__(13285);
|
|
const validate_fix_command_is_supported_1 = __webpack_require__(16117);
|
|
const get_display_path_1 = __webpack_require__(79898);
|
|
const chalk_1 = __webpack_require__(32589);
|
|
const theme_1 = __webpack_require__(86988);
|
|
const check_paths_1 = __webpack_require__(94501);
|
|
const debug = Debug('snyk-fix');
|
|
const snykFixFeatureFlag = 'cliSnykFix';
|
|
async function fix(...args) {
|
|
const { options: rawOptions, paths } = await process_command_args_1.processCommandArgs(...args);
|
|
const options = set_default_test_options_1.setDefaultTestOptions(rawOptions);
|
|
debug(options);
|
|
await validate_fix_command_is_supported_1.validateFixCommandIsSupported(options);
|
|
if (!options.docker) {
|
|
check_paths_1.checkOSSPaths(paths, rawOptions);
|
|
}
|
|
validate_test_options_1.validateTestOptions(options);
|
|
validate_credentials_1.validateCredentials(options);
|
|
const results = [];
|
|
results.push(...(await runSnykTestLegacy(options, paths)));
|
|
// fix
|
|
debug(`Organization has ${snykFixFeatureFlag} feature flag enabled for experimental Snyk fix functionality`);
|
|
const vulnerableResults = results.filter((res) => Object.keys(res.testResult.issues).length);
|
|
const { dryRun, quiet, sequential: sequentialFix } = options;
|
|
const { fixSummary, meta, results: resultsByPlugin } = await snykFix.fix(results, {
|
|
dryRun,
|
|
quiet,
|
|
sequentialFix,
|
|
});
|
|
setSnykFixAnalytics(fixSummary, meta, results, resultsByPlugin, vulnerableResults);
|
|
// `snyk test` did not return any test results
|
|
if (results.length === 0) {
|
|
throw new Error(fixSummary);
|
|
}
|
|
// `snyk test` returned no vulnerable results, so nothing to fix
|
|
if (vulnerableResults.length === 0) {
|
|
return fixSummary;
|
|
}
|
|
// `snyk test` returned vulnerable results
|
|
// however some errors occurred during `snyk fix` and nothing was fixed in the end
|
|
const anyFailed = meta.failed > 0;
|
|
const noneFixed = meta.fixed === 0;
|
|
if (anyFailed && noneFixed) {
|
|
throw new Error(fixSummary);
|
|
}
|
|
return fixSummary;
|
|
}
|
|
exports.default = fix;
|
|
/* @deprecated
|
|
* TODO: once project envelope is default all code below will be deleted
|
|
* we should be calling test via new Ecosystems instead
|
|
*/
|
|
async function runSnykTestLegacy(options, paths) {
|
|
const results = [];
|
|
const stdOutSpinner = ora({
|
|
isSilent: options.quiet,
|
|
stream: process.stdout,
|
|
});
|
|
const stdErrSpinner = ora({
|
|
isSilent: options.quiet,
|
|
stream: process.stdout,
|
|
});
|
|
stdErrSpinner.start();
|
|
stdOutSpinner.start();
|
|
for (const path of paths) {
|
|
let displayPath = path;
|
|
const spinnerMessage = `Running \`snyk test\` for ${displayPath}`;
|
|
try {
|
|
displayPath = get_display_path_1.getDisplayPath(path);
|
|
stdOutSpinner.text = spinnerMessage;
|
|
stdOutSpinner.render();
|
|
// Create a copy of the options so a specific test can
|
|
// modify them i.e. add `options.file` etc. We'll need
|
|
// these options later.
|
|
const snykTestOptions = {
|
|
...options,
|
|
path,
|
|
projectName: options['project-name'],
|
|
};
|
|
const testResults = [];
|
|
const testResultForPath = await snyk.test(path, { ...snykTestOptions, quiet: true });
|
|
testResults.push(...(Array.isArray(testResultForPath)
|
|
? testResultForPath
|
|
: [testResultForPath]));
|
|
const newRes = convert_legacy_tests_results_to_fix_entities_1.convertLegacyTestResultToFixEntities(testResults, path, options);
|
|
results.push(...newRes);
|
|
stdOutSpinner.stopAndPersist({
|
|
text: spinnerMessage,
|
|
symbol: `\n${theme_1.icon.RUN}`,
|
|
});
|
|
}
|
|
catch (error) {
|
|
const testError = format_test_error_1.formatTestError(error);
|
|
const userMessage = theme_1.color.status.error(`Failed! ${testError.message}.`) +
|
|
`\n Tip: run \`snyk test ${displayPath} -d\` for more information.`;
|
|
stdOutSpinner.stopAndPersist({
|
|
text: spinnerMessage,
|
|
symbol: `\n${theme_1.icon.RUN}`,
|
|
});
|
|
stdErrSpinner.stopAndPersist({
|
|
text: userMessage,
|
|
symbol: chalk_1.default.red(' '),
|
|
});
|
|
debug(userMessage);
|
|
}
|
|
}
|
|
stdOutSpinner.stop();
|
|
stdErrSpinner.stop();
|
|
return results;
|
|
}
|
|
function setSnykFixAnalytics(fixSummary, meta, snykTestResponses, resultsByPlugin, vulnerableResults) {
|
|
// Analytics # of projects
|
|
analytics.add('snykFixFailedProjects', meta.failed);
|
|
analytics.add('snykFixFixedProjects', meta.fixed);
|
|
analytics.add('snykFixTotalProjects', snykTestResponses.length);
|
|
analytics.add('snykFixVulnerableProjects', vulnerableResults.length);
|
|
// Analytics # of issues
|
|
analytics.add('snykFixFixableIssues', meta.fixableIssues);
|
|
analytics.add('snykFixFixedIssues', meta.fixedIssues);
|
|
analytics.add('snykFixTotalIssues', meta.totalIssues);
|
|
analytics.add('snykFixSummary', fixSummary);
|
|
// Analytics for errors
|
|
for (const plugin of Object.keys(resultsByPlugin)) {
|
|
const errors = [];
|
|
const failedToFix = resultsByPlugin[plugin].failed;
|
|
for (const failed of failedToFix) {
|
|
if ('error' in failed) {
|
|
errors.push(failed.error.message);
|
|
}
|
|
if ('changes' in failed) {
|
|
errors.push(...failed.changes.map((f) => JSON.stringify(f)));
|
|
}
|
|
}
|
|
analytics.add('snykFixErrors', { [plugin]: errors });
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 16117:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.validateFixCommandIsSupported = void 0;
|
|
const Debug = __webpack_require__(15158);
|
|
const ecosystems_1 = __webpack_require__(5168);
|
|
const feature_flags_1 = __webpack_require__(63011);
|
|
const not_supported_by_ecosystem_1 = __webpack_require__(72571);
|
|
const errors_1 = __webpack_require__(55191);
|
|
const chalk_1 = __webpack_require__(32589);
|
|
const debug = Debug('snyk-fix');
|
|
const snykFixFeatureFlag = 'cliSnykFix';
|
|
async function validateFixCommandIsSupported(options) {
|
|
if (options.docker) {
|
|
throw new not_supported_by_ecosystem_1.FeatureNotSupportedByEcosystemError('snyk fix', 'docker');
|
|
}
|
|
const ecosystem = ecosystems_1.getEcosystemForTest(options);
|
|
if (ecosystem) {
|
|
throw new not_supported_by_ecosystem_1.FeatureNotSupportedByEcosystemError('snyk fix', ecosystem);
|
|
}
|
|
const snykFixSupported = await feature_flags_1.isFeatureFlagSupportedForOrg(snykFixFeatureFlag, options.org);
|
|
debug('Feature flag check returned: ', snykFixSupported);
|
|
if (snykFixSupported.code === 401 || snykFixSupported.code === 403) {
|
|
throw errors_1.AuthFailedError(snykFixSupported.error, snykFixSupported.code);
|
|
}
|
|
if (!snykFixSupported.ok) {
|
|
const snykFixErrorMessage = chalk_1.default.red(`\`snyk fix\` is not supported${options.org ? ` for org '${options.org}'` : ''}.`) +
|
|
'\nSee documentation on how to enable this beta feature: https://docs.snyk.io/snyk-cli/fix-vulnerabilities-from-the-cli/automatic-remediation-with-snyk-fix#enabling-snyk-fix';
|
|
const unsupportedError = new Error(snykFixErrorMessage);
|
|
throw unsupportedError;
|
|
}
|
|
return true;
|
|
}
|
|
exports.validateFixCommandIsSupported = validateFixCommandIsSupported;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 68214:
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.formatTestError = void 0;
|
|
function formatTestError(error) {
|
|
// Possible error cases:
|
|
// - the test found some vulns. `error.message` is a
|
|
// JSON-stringified
|
|
// test result.
|
|
// - the flow failed, `error` is a real Error object.
|
|
// - the flow failed, `error` is a number or string
|
|
// describing the problem.
|
|
//
|
|
// To standardise this, make sure we use the best _object_ to
|
|
// describe the error.
|
|
let errorResponse;
|
|
if (error instanceof Error) {
|
|
errorResponse = error;
|
|
}
|
|
else if (typeof error !== 'object') {
|
|
errorResponse = new Error(error);
|
|
}
|
|
else {
|
|
try {
|
|
errorResponse = JSON.parse(error.message);
|
|
}
|
|
catch (unused) {
|
|
errorResponse = error;
|
|
}
|
|
}
|
|
return errorResponse;
|
|
}
|
|
exports.formatTestError = formatTestError;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 13285:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.setDefaultTestOptions = void 0;
|
|
const config_1 = __webpack_require__(25425);
|
|
function setDefaultTestOptions(options) {
|
|
const svpSupplied = (options['show-vulnerable-paths'] || '')
|
|
.toString()
|
|
.toLowerCase();
|
|
delete options['show-vulnerable-paths'];
|
|
return {
|
|
...options,
|
|
// org fallback to config unless specified
|
|
org: options.org || config_1.default.org,
|
|
// making `show-vulnerable-paths` 'some' by default.
|
|
showVulnPaths: showVulnPathsMapping[svpSupplied] || 'some',
|
|
};
|
|
}
|
|
exports.setDefaultTestOptions = setDefaultTestOptions;
|
|
const showVulnPathsMapping = {
|
|
false: 'none',
|
|
none: 'none',
|
|
true: 'some',
|
|
some: 'some',
|
|
all: 'all',
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 4593:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.validateCredentials = void 0;
|
|
const api_token_1 = __webpack_require__(95181);
|
|
function validateCredentials(options) {
|
|
try {
|
|
api_token_1.apiTokenExists();
|
|
}
|
|
catch (err) {
|
|
if (api_token_1.getOAuthToken()) {
|
|
return;
|
|
}
|
|
else if (options.docker && api_token_1.getDockerToken()) {
|
|
options.testDepGraphDockerEndpoint = '/docker-jwt/test-dependencies';
|
|
options.isDockerUser = true;
|
|
}
|
|
else {
|
|
throw err;
|
|
}
|
|
}
|
|
}
|
|
exports.validateCredentials = validateCredentials;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 83476:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.validateTestOptions = void 0;
|
|
const theme_1 = __webpack_require__(86988);
|
|
const common_1 = __webpack_require__(53110);
|
|
const fail_on_error_ts_1 = __webpack_require__(18195);
|
|
function validateTestOptions(options) {
|
|
if (options.severityThreshold &&
|
|
!validateSeverityThreshold(options.severityThreshold)) {
|
|
throw new Error('INVALID_SEVERITY_THRESHOLD');
|
|
}
|
|
if (options.failOn && !validateFailOn(options.failOn)) {
|
|
const error = new fail_on_error_ts_1.FailOnError();
|
|
throw theme_1.color.status.error(error.message);
|
|
}
|
|
}
|
|
exports.validateTestOptions = validateTestOptions;
|
|
function validateSeverityThreshold(severityThreshold) {
|
|
return common_1.SEVERITIES.map((s) => s.verboseName).indexOf(severityThreshold) > -1;
|
|
}
|
|
function validateFailOn(arg) {
|
|
return Object.keys(common_1.FAIL_ON).includes(arg);
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 18195:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.FailOnError = void 0;
|
|
const custom_error_1 = __webpack_require__(17188);
|
|
const common_1 = __webpack_require__(53110);
|
|
class FailOnError extends custom_error_1.CustomError {
|
|
constructor() {
|
|
super(FailOnError.ERROR_MESSAGE);
|
|
}
|
|
}
|
|
exports.FailOnError = FailOnError;
|
|
FailOnError.ERROR_MESSAGE = 'Invalid fail on argument, please use one of: ' +
|
|
Object.keys(common_1.FAIL_ON).join(' | ');
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 72571:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.FeatureNotSupportedByEcosystemError = void 0;
|
|
const custom_error_1 = __webpack_require__(17188);
|
|
class FeatureNotSupportedByEcosystemError extends custom_error_1.CustomError {
|
|
constructor(feature, ecosystem) {
|
|
super(`Unsupported ecosystem ${ecosystem} for ${feature}.`);
|
|
this.code = 422;
|
|
this.feature = feature;
|
|
this.userMessage = `\`${feature}\` is not supported for ecosystem '${ecosystem}'`;
|
|
}
|
|
}
|
|
exports.FeatureNotSupportedByEcosystemError = FeatureNotSupportedByEcosystemError;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 53776:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.extractMeta = exports.groupEntitiesPerScanType = exports.fix = void 0;
|
|
const debugLib = __webpack_require__(15158);
|
|
const pMap = __webpack_require__(54270);
|
|
const ora = __webpack_require__(63395);
|
|
const chalk = __webpack_require__(98250);
|
|
const outputFormatter = __webpack_require__(70962);
|
|
const load_plugin_1 = __webpack_require__(65090);
|
|
const partition_by_vulnerable_1 = __webpack_require__(24957);
|
|
const error_to_user_message_1 = __webpack_require__(5258);
|
|
const total_issues_count_1 = __webpack_require__(41160);
|
|
const fixable_issues_1 = __webpack_require__(86635);
|
|
const debug = debugLib('snyk-fix:main');
|
|
async function fix(entities, options = {
|
|
dryRun: false,
|
|
quiet: false,
|
|
stripAnsi: false,
|
|
}) {
|
|
debug('Running snyk fix with options:', options);
|
|
const spinner = ora({ isSilent: options.quiet, stream: process.stdout });
|
|
let resultsByPlugin = {};
|
|
const { vulnerable, notVulnerable: nothingToFix, } = await partition_by_vulnerable_1.partitionByVulnerable(entities);
|
|
const entitiesPerType = groupEntitiesPerScanType(vulnerable);
|
|
const exceptions = {};
|
|
await pMap(Object.keys(entitiesPerType), async (scanType) => {
|
|
try {
|
|
const fixPlugin = load_plugin_1.loadPlugin(scanType);
|
|
const results = await fixPlugin(entitiesPerType[scanType], options);
|
|
resultsByPlugin = { ...resultsByPlugin, ...results };
|
|
}
|
|
catch (e) {
|
|
debug(`Failed to processes ${scanType}`, e);
|
|
exceptions[scanType] = {
|
|
originals: entitiesPerType[scanType],
|
|
userMessage: error_to_user_message_1.convertErrorToUserMessage(e),
|
|
};
|
|
}
|
|
}, {
|
|
concurrency: 3,
|
|
});
|
|
const fixSummary = await outputFormatter.showResultsSummary(nothingToFix, resultsByPlugin, exceptions, options, entities.length);
|
|
const meta = extractMeta(resultsByPlugin, exceptions);
|
|
spinner.start();
|
|
if (meta.fixed > 0) {
|
|
spinner.stopAndPersist({
|
|
text: 'Done',
|
|
symbol: chalk.green('✔'),
|
|
});
|
|
}
|
|
else {
|
|
spinner.stop();
|
|
}
|
|
return {
|
|
results: resultsByPlugin,
|
|
exceptions,
|
|
fixSummary,
|
|
meta,
|
|
};
|
|
}
|
|
exports.fix = fix;
|
|
function groupEntitiesPerScanType(entities) {
|
|
var _a, _b, _c;
|
|
const entitiesPerType = {};
|
|
for (const entity of entities) {
|
|
// TODO: group all node
|
|
const type = (_c = (_b = (_a = entity.scanResult) === null || _a === void 0 ? void 0 : _a.identity) === null || _b === void 0 ? void 0 : _b.type) !== null && _c !== void 0 ? _c : 'missing-type';
|
|
if (entitiesPerType[type]) {
|
|
entitiesPerType[type].push(entity);
|
|
continue;
|
|
}
|
|
entitiesPerType[type] = [entity];
|
|
}
|
|
return entitiesPerType;
|
|
}
|
|
exports.groupEntitiesPerScanType = groupEntitiesPerScanType;
|
|
function extractMeta(resultsByPlugin, exceptions) {
|
|
const testResults = outputFormatter.getTestResults(resultsByPlugin, exceptions);
|
|
const issueData = testResults.map((i) => i.issuesData);
|
|
const failed = outputFormatter.calculateFailed(resultsByPlugin, exceptions);
|
|
const fixed = outputFormatter.calculateFixed(resultsByPlugin);
|
|
const totalIssueCount = total_issues_count_1.getTotalIssueCount(issueData);
|
|
const { count: fixableCount } = fixable_issues_1.hasFixableIssues(testResults);
|
|
const fixedIssueCount = outputFormatter.calculateFixedIssues(resultsByPlugin);
|
|
return {
|
|
fixed,
|
|
failed,
|
|
totalIssues: totalIssueCount,
|
|
fixableIssues: fixableCount,
|
|
fixedIssues: fixedIssueCount,
|
|
};
|
|
}
|
|
exports.extractMeta = extractMeta;
|
|
//# sourceMappingURL=index.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 72353:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.CommandFailedError = void 0;
|
|
const custom_error_1 = __webpack_require__(33129);
|
|
class CommandFailedError extends custom_error_1.CustomError {
|
|
constructor(customMessage, command) {
|
|
super(customMessage, custom_error_1.ERROR_CODES.CommandFailed);
|
|
this.command = command;
|
|
}
|
|
}
|
|
exports.CommandFailedError = CommandFailedError;
|
|
//# sourceMappingURL=command-failed-to-run-error.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 75391:
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.contactSupportMessage = exports.reTryMessage = void 0;
|
|
exports.reTryMessage = 'Tip: Re-run in debug mode to see more information: DEBUG=*snyk* <COMMAND>';
|
|
exports.contactSupportMessage = 'If the issue persists contact support@snyk.io';
|
|
//# sourceMappingURL=common.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 33129:
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.ERROR_CODES = exports.CustomError = void 0;
|
|
class CustomError extends Error {
|
|
constructor(message, errorCode) {
|
|
super(message);
|
|
this.name = this.constructor.name;
|
|
this.innerError = undefined;
|
|
this.errorCode = errorCode;
|
|
}
|
|
}
|
|
exports.CustomError = CustomError;
|
|
var ERROR_CODES;
|
|
(function (ERROR_CODES) {
|
|
ERROR_CODES["UnsupportedTypeError"] = "G10";
|
|
ERROR_CODES["MissingRemediationData"] = "G11";
|
|
ERROR_CODES["MissingFileName"] = "G12";
|
|
ERROR_CODES["FailedToParseManifest"] = "G13";
|
|
ERROR_CODES["CommandFailed"] = "G14";
|
|
ERROR_CODES["NoFixesCouldBeApplied"] = "G15";
|
|
})(ERROR_CODES = exports.ERROR_CODES || (exports.ERROR_CODES = {}));
|
|
//# sourceMappingURL=custom-error.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 5258:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.convertErrorToUserMessage = void 0;
|
|
const unsupported_type_error_1 = __webpack_require__(90361);
|
|
function convertErrorToUserMessage(error) {
|
|
if (error instanceof unsupported_type_error_1.UnsupportedTypeError) {
|
|
return `${error.scanType} is not supported.`;
|
|
}
|
|
return error.message;
|
|
}
|
|
exports.convertErrorToUserMessage = convertErrorToUserMessage;
|
|
//# sourceMappingURL=error-to-user-message.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 84657:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.FailedToParseManifest = void 0;
|
|
const custom_error_1 = __webpack_require__(33129);
|
|
class FailedToParseManifest extends custom_error_1.CustomError {
|
|
constructor() {
|
|
super('Failed to parse manifest', custom_error_1.ERROR_CODES.FailedToParseManifest);
|
|
}
|
|
}
|
|
exports.FailedToParseManifest = FailedToParseManifest;
|
|
//# sourceMappingURL=failed-to-parse-manifest.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 86920:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.MissingFileNameError = void 0;
|
|
const custom_error_1 = __webpack_require__(33129);
|
|
class MissingFileNameError extends custom_error_1.CustomError {
|
|
constructor() {
|
|
super('Filename is missing from test result', custom_error_1.ERROR_CODES.MissingFileName);
|
|
}
|
|
}
|
|
exports.MissingFileNameError = MissingFileNameError;
|
|
//# sourceMappingURL=missing-file-name.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 95084:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.MissingRemediationDataError = void 0;
|
|
const custom_error_1 = __webpack_require__(33129);
|
|
class MissingRemediationDataError extends custom_error_1.CustomError {
|
|
constructor() {
|
|
super('Remediation data is required to apply fixes', custom_error_1.ERROR_CODES.MissingRemediationData);
|
|
}
|
|
}
|
|
exports.MissingRemediationDataError = MissingRemediationDataError;
|
|
//# sourceMappingURL=missing-remediation-data.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 80799:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.NoFixesCouldBeAppliedError = void 0;
|
|
const custom_error_1 = __webpack_require__(33129);
|
|
class NoFixesCouldBeAppliedError extends custom_error_1.CustomError {
|
|
constructor(message, tip) {
|
|
super(message || 'No fixes could be applied', custom_error_1.ERROR_CODES.NoFixesCouldBeApplied);
|
|
this.tip = tip;
|
|
}
|
|
}
|
|
exports.NoFixesCouldBeAppliedError = NoFixesCouldBeAppliedError;
|
|
//# sourceMappingURL=no-fixes-applied.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 90361:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.UnsupportedTypeError = void 0;
|
|
const custom_error_1 = __webpack_require__(33129);
|
|
class UnsupportedTypeError extends custom_error_1.CustomError {
|
|
constructor(scanType) {
|
|
super('Provided scan type is not supported', custom_error_1.ERROR_CODES.UnsupportedTypeError);
|
|
this.scanType = scanType;
|
|
}
|
|
}
|
|
exports.UnsupportedTypeError = UnsupportedTypeError;
|
|
//# sourceMappingURL=unsupported-type-error.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 86635:
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.hasFixableIssues = void 0;
|
|
function hasFixableIssues(results) {
|
|
let hasFixes = false;
|
|
let count = 0;
|
|
for (const result of Object.values(results)) {
|
|
const { remediation } = result;
|
|
if (remediation) {
|
|
const { upgrade, pin, patch } = remediation;
|
|
const upgrades = Object.keys(upgrade);
|
|
const pins = Object.keys(pin);
|
|
if (pins.length || upgrades.length) {
|
|
hasFixes = true;
|
|
// pins & upgrades are mutually exclusive
|
|
count += getUpgradableIssues(pins.length ? pin : upgrade);
|
|
}
|
|
const patches = Object.keys(patch);
|
|
if (patches.length) {
|
|
hasFixes = true;
|
|
count += patches.length;
|
|
}
|
|
}
|
|
}
|
|
return {
|
|
hasFixes,
|
|
count,
|
|
};
|
|
}
|
|
exports.hasFixableIssues = hasFixableIssues;
|
|
function getUpgradableIssues(updates) {
|
|
const issues = [];
|
|
for (const id of Object.keys(updates)) {
|
|
issues.push(...updates[id].vulns);
|
|
}
|
|
return issues.length;
|
|
}
|
|
//# sourceMappingURL=fixable-issues.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 29748:
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.getIssueCountBySeverity = void 0;
|
|
function getIssueCountBySeverity(issueData) {
|
|
const total = {
|
|
low: [],
|
|
medium: [],
|
|
high: [],
|
|
critical: [],
|
|
};
|
|
for (const entry of issueData) {
|
|
for (const issue of Object.values(entry)) {
|
|
const { severity, id } = issue;
|
|
total[severity.toLowerCase()].push(id);
|
|
}
|
|
}
|
|
return total;
|
|
}
|
|
exports.getIssueCountBySeverity = getIssueCountBySeverity;
|
|
//# sourceMappingURL=issues-by-severity.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 41160:
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.getTotalIssueCount = void 0;
|
|
function getTotalIssueCount(issueData) {
|
|
let total = 0;
|
|
for (const entry of issueData) {
|
|
total += Object.keys(entry).length;
|
|
}
|
|
return total;
|
|
}
|
|
exports.getTotalIssueCount = getTotalIssueCount;
|
|
//# sourceMappingURL=total-issues-count.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 90686:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.formatDisplayName = void 0;
|
|
const pathLib = __webpack_require__(85622);
|
|
function formatDisplayName(path, identity) {
|
|
if (!identity.targetFile) {
|
|
return `${identity.type} project`;
|
|
}
|
|
// show paths relative to where `snyk fix` is running
|
|
return pathLib.relative(process.cwd(), pathLib.join(path, identity.targetFile));
|
|
}
|
|
exports.formatDisplayName = formatDisplayName;
|
|
//# sourceMappingURL=format-display-name.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 31998:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.formatFailed = void 0;
|
|
const types_1 = __webpack_require__(71538);
|
|
const error_to_user_message_1 = __webpack_require__(5258);
|
|
const format_with_changes_item_1 = __webpack_require__(38154);
|
|
const format_unresolved_item_1 = __webpack_require__(82187);
|
|
function formatFailed(failed) {
|
|
if (types_1.isWithError(failed)) {
|
|
return format_unresolved_item_1.formatUnresolved(failed.original, error_to_user_message_1.convertErrorToUserMessage(failed.error), failed.tip);
|
|
}
|
|
return format_with_changes_item_1.formatChangesSummary(failed.original, failed.changes);
|
|
}
|
|
exports.formatFailed = formatFailed;
|
|
//# sourceMappingURL=format-failed-item.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 82187:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.formatUnresolved = void 0;
|
|
const chalk = __webpack_require__(98250);
|
|
const format_display_name_1 = __webpack_require__(90686);
|
|
const show_results_summary_1 = __webpack_require__(70962);
|
|
function formatUnresolved(entity, userMessage, tip) {
|
|
const name = format_display_name_1.formatDisplayName(entity.workspace.path, entity.scanResult.identity);
|
|
const tipMessage = tip ? `\n${show_results_summary_1.PADDING_SPACE}Tip: ${tip}` : '';
|
|
const errorMessage = `${show_results_summary_1.PADDING_SPACE}${name}\n${show_results_summary_1.PADDING_SPACE}${chalk.red('✖')} ${chalk.red(userMessage)}`;
|
|
return errorMessage + tipMessage;
|
|
}
|
|
exports.formatUnresolved = formatUnresolved;
|
|
//# sourceMappingURL=format-unresolved-item.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 38154:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.formatChangesSummary = void 0;
|
|
const chalk = __webpack_require__(98250);
|
|
const format_display_name_1 = __webpack_require__(90686);
|
|
const show_results_summary_1 = __webpack_require__(70962);
|
|
/*
|
|
* Generate formatted output that describes what changes were applied, which failed.
|
|
*/
|
|
function formatChangesSummary(entity, changes) {
|
|
return `${show_results_summary_1.PADDING_SPACE}${format_display_name_1.formatDisplayName(entity.workspace.path, entity.scanResult.identity)}\n${changes.map((c) => formatAppliedChange(c)).join('\n')}`;
|
|
}
|
|
exports.formatChangesSummary = formatChangesSummary;
|
|
function formatAppliedChange(change) {
|
|
if (change.success === true) {
|
|
return `${show_results_summary_1.PADDING_SPACE}${chalk.green('✔')} ${change.userMessage}`;
|
|
}
|
|
if (change.success === false) {
|
|
return `${show_results_summary_1.PADDING_SPACE}${chalk.red('x')} ${chalk.red(change.userMessage)}\n${show_results_summary_1.PADDING_SPACE}Reason:${show_results_summary_1.PADDING_SPACE}${change.reason}${change.tip ? `.\n${show_results_summary_1.PADDING_SPACE}Tip: ${change.tip}` : undefined}`;
|
|
}
|
|
return '';
|
|
}
|
|
//# sourceMappingURL=format-with-changes-item.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 70962:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.getTestResults = exports.generateIssueSummary = exports.getSeveritiesColour = exports.defaultSeverityColor = exports.severitiesColourMapping = exports.formatIssueCountBySeverity = exports.calculateFailed = exports.calculateFixedIssues = exports.calculateFixed = exports.generateOverallSummary = exports.generateUnresolvedSummary = exports.generateSuccessfulFixesSummary = exports.showResultsSummary = exports.PADDING_SPACE = void 0;
|
|
const chalk = __webpack_require__(98250);
|
|
const stripAnsi = __webpack_require__(71990);
|
|
const common_1 = __webpack_require__(75391);
|
|
const fixable_issues_1 = __webpack_require__(86635);
|
|
const issues_by_severity_1 = __webpack_require__(29748);
|
|
const total_issues_count_1 = __webpack_require__(41160);
|
|
const format_failed_item_1 = __webpack_require__(31998);
|
|
const format_with_changes_item_1 = __webpack_require__(38154);
|
|
const format_unresolved_item_1 = __webpack_require__(82187);
|
|
exports.PADDING_SPACE = ' '; // 2 spaces
|
|
async function showResultsSummary(nothingToFix, resultsByPlugin, exceptions, options, total) {
|
|
const successfulFixesSummary = generateSuccessfulFixesSummary(resultsByPlugin);
|
|
const { summary: unresolvedSummary, count: unresolvedCount, } = generateUnresolvedSummary(resultsByPlugin, exceptions);
|
|
const { summary: overallSummary, count: changedCount, } = generateOverallSummary(resultsByPlugin, exceptions, nothingToFix, options);
|
|
const getHelpText = `${common_1.reTryMessage}. ${common_1.contactSupportMessage}`;
|
|
// called without any `snyk test` results
|
|
if (total === 0) {
|
|
const summary = `\n${chalk.red(' ✖ No successful fixes')}`;
|
|
return options.stripAnsi ? stripAnsi(summary) : summary;
|
|
}
|
|
// 100% not vulnerable and had no errors/unsupported
|
|
if (nothingToFix.length === total && unresolvedCount === 0) {
|
|
const summary = `\n${chalk.green('✔ No vulnerable items to fix')}\n\n${overallSummary}`;
|
|
return options.stripAnsi ? stripAnsi(summary) : summary;
|
|
}
|
|
const summary = `\n${successfulFixesSummary}${unresolvedSummary}${unresolvedCount || changedCount ? `\n\n${overallSummary}` : ''}${unresolvedSummary ? `\n\n${getHelpText}` : ''}`;
|
|
return options.stripAnsi ? stripAnsi(summary) : summary;
|
|
}
|
|
exports.showResultsSummary = showResultsSummary;
|
|
function generateSuccessfulFixesSummary(resultsByPlugin) {
|
|
const sectionTitle = 'Successful fixes:';
|
|
const formattedTitleHeader = `${chalk.bold(sectionTitle)}`;
|
|
let summary = '';
|
|
for (const plugin of Object.keys(resultsByPlugin)) {
|
|
const fixedSuccessfully = resultsByPlugin[plugin].succeeded;
|
|
if (fixedSuccessfully.length > 0) {
|
|
summary +=
|
|
'\n\n' +
|
|
fixedSuccessfully
|
|
.map((s) => format_with_changes_item_1.formatChangesSummary(s.original, s.changes))
|
|
.join('\n\n');
|
|
}
|
|
}
|
|
if (summary) {
|
|
return formattedTitleHeader + summary;
|
|
}
|
|
return chalk.red(' ✖ No successful fixes\n');
|
|
}
|
|
exports.generateSuccessfulFixesSummary = generateSuccessfulFixesSummary;
|
|
function generateUnresolvedSummary(resultsByPlugin, exceptionsByScanType) {
|
|
const title = 'Unresolved items:';
|
|
const formattedTitle = `${chalk.bold(title)}`;
|
|
let summary = '';
|
|
let count = 0;
|
|
for (const plugin of Object.keys(resultsByPlugin)) {
|
|
const skipped = resultsByPlugin[plugin].skipped;
|
|
if (skipped.length > 0) {
|
|
count += skipped.length;
|
|
summary +=
|
|
'\n\n' +
|
|
skipped
|
|
.map((s) => format_unresolved_item_1.formatUnresolved(s.original, s.userMessage))
|
|
.join('\n\n');
|
|
}
|
|
const failed = resultsByPlugin[plugin].failed;
|
|
if (failed.length > 0) {
|
|
count += failed.length;
|
|
summary += '\n\n' + failed.map((s) => format_failed_item_1.formatFailed(s)).join('\n\n');
|
|
}
|
|
}
|
|
if (Object.keys(exceptionsByScanType).length) {
|
|
for (const ecosystem of Object.keys(exceptionsByScanType)) {
|
|
const unresolved = exceptionsByScanType[ecosystem];
|
|
count += unresolved.originals.length;
|
|
summary +=
|
|
'\n\n' +
|
|
unresolved.originals
|
|
.map((s) => format_unresolved_item_1.formatUnresolved(s, unresolved.userMessage))
|
|
.join('\n\n');
|
|
}
|
|
}
|
|
if (summary) {
|
|
return { summary: `\n\n${formattedTitle}${summary}`, count };
|
|
}
|
|
return { summary: '', count: 0 };
|
|
}
|
|
exports.generateUnresolvedSummary = generateUnresolvedSummary;
|
|
function generateOverallSummary(resultsByPlugin, exceptions, nothingToFix, options) {
|
|
const sectionTitle = 'Summary:';
|
|
const formattedTitleHeader = `${chalk.bold(sectionTitle)}`;
|
|
const fixed = calculateFixed(resultsByPlugin);
|
|
const failed = calculateFailed(resultsByPlugin, exceptions);
|
|
const dryRunText = options.dryRun
|
|
? chalk.hex('#EDD55E')(`${exports.PADDING_SPACE}Command run in ${chalk.bold('dry run')} mode. Fixes are not applied.\n`)
|
|
: '';
|
|
const notFixedMessage = failed > 0
|
|
? `${exports.PADDING_SPACE}${chalk.bold.red(failed)} items were not fixed\n`
|
|
: '';
|
|
const fixedMessage = fixed > 0
|
|
? `${exports.PADDING_SPACE}${chalk.green.bold(fixed)} items were successfully fixed\n`
|
|
: '';
|
|
const vulnsSummary = generateIssueSummary(resultsByPlugin, exceptions);
|
|
const notVulnerableSummary = nothingToFix.length > 0
|
|
? `${exports.PADDING_SPACE}${nothingToFix.length} items were not vulnerable\n`
|
|
: '';
|
|
return {
|
|
summary: `${formattedTitleHeader}\n\n${dryRunText}${notFixedMessage}${fixedMessage}${notVulnerableSummary}${vulnsSummary}`,
|
|
count: fixed + failed,
|
|
};
|
|
}
|
|
exports.generateOverallSummary = generateOverallSummary;
|
|
function calculateFixed(resultsByPlugin) {
|
|
let fixed = 0;
|
|
for (const plugin of Object.keys(resultsByPlugin)) {
|
|
fixed += resultsByPlugin[plugin].succeeded.length;
|
|
}
|
|
return fixed;
|
|
}
|
|
exports.calculateFixed = calculateFixed;
|
|
function calculateFixedIssues(resultsByPlugin) {
|
|
const fixedIssues = [];
|
|
for (const plugin of Object.keys(resultsByPlugin)) {
|
|
for (const entity of resultsByPlugin[plugin].succeeded) {
|
|
// count unique vulns fixed per scanned entity
|
|
// some fixed may need to be made in multiple places
|
|
// and would count multiple times otherwise.
|
|
const fixedPerEntity = new Set();
|
|
entity.changes
|
|
.filter((c) => c.success)
|
|
.forEach((c) => {
|
|
c.issueIds.map((i) => fixedPerEntity.add(i));
|
|
});
|
|
fixedIssues.push(...Array.from(fixedPerEntity));
|
|
}
|
|
}
|
|
return fixedIssues.length;
|
|
}
|
|
exports.calculateFixedIssues = calculateFixedIssues;
|
|
function calculateFailed(resultsByPlugin, exceptions) {
|
|
let failed = 0;
|
|
for (const plugin of Object.keys(resultsByPlugin)) {
|
|
const results = resultsByPlugin[plugin];
|
|
failed += results.failed.length + results.skipped.length;
|
|
}
|
|
if (Object.keys(exceptions).length) {
|
|
for (const ecosystem of Object.keys(exceptions)) {
|
|
const unresolved = exceptions[ecosystem];
|
|
failed += unresolved.originals.length;
|
|
}
|
|
}
|
|
return failed;
|
|
}
|
|
exports.calculateFailed = calculateFailed;
|
|
function formatIssueCountBySeverity({ critical, high, medium, low, }) {
|
|
const summary = [];
|
|
if (critical && critical > 0) {
|
|
summary.push(exports.severitiesColourMapping.critical.colorFunc(`${critical} Critical`));
|
|
}
|
|
if (high && high > 0) {
|
|
summary.push(exports.severitiesColourMapping.high.colorFunc(`${high} High`));
|
|
}
|
|
if (medium && medium > 0) {
|
|
summary.push(exports.severitiesColourMapping.medium.colorFunc(`${medium} Medium`));
|
|
}
|
|
if (low && low > 0) {
|
|
summary.push(exports.severitiesColourMapping.low.colorFunc(`${low} Low`));
|
|
}
|
|
return summary.join(' | ');
|
|
}
|
|
exports.formatIssueCountBySeverity = formatIssueCountBySeverity;
|
|
exports.severitiesColourMapping = {
|
|
low: {
|
|
colorFunc(text) {
|
|
return chalk.hex('#BCBBC8')(text);
|
|
},
|
|
},
|
|
medium: {
|
|
colorFunc(text) {
|
|
return chalk.hex('#EDD55E')(text);
|
|
},
|
|
},
|
|
high: {
|
|
colorFunc(text) {
|
|
return chalk.hex('#FF872F')(text);
|
|
},
|
|
},
|
|
critical: {
|
|
colorFunc(text) {
|
|
return chalk.hex('#FF0B0B')(text);
|
|
},
|
|
},
|
|
};
|
|
exports.defaultSeverityColor = {
|
|
colorFunc(text) {
|
|
return chalk.grey(text);
|
|
},
|
|
};
|
|
function getSeveritiesColour(severity) {
|
|
var _a;
|
|
return (_a = exports.severitiesColourMapping[severity]) !== null && _a !== void 0 ? _a : exports.defaultSeverityColor;
|
|
}
|
|
exports.getSeveritiesColour = getSeveritiesColour;
|
|
function generateIssueSummary(resultsByPlugin, exceptions) {
|
|
const testResults = getTestResults(resultsByPlugin, exceptions);
|
|
const issueData = testResults.map((i) => i.issuesData);
|
|
const bySeverity = issues_by_severity_1.getIssueCountBySeverity(issueData);
|
|
const issuesBySeverityMessage = formatIssueCountBySeverity({
|
|
critical: bySeverity.critical.length,
|
|
high: bySeverity.high.length,
|
|
medium: bySeverity.medium.length,
|
|
low: bySeverity.low.length,
|
|
});
|
|
// can't use .flat() or .flatMap() because it's not supported in Node 10
|
|
const issues = [];
|
|
for (const result of testResults) {
|
|
issues.push(...result.issues);
|
|
}
|
|
const totalIssueCount = total_issues_count_1.getTotalIssueCount(issueData);
|
|
let totalIssues = '';
|
|
if (totalIssueCount > 0) {
|
|
totalIssues = `${chalk.bold(totalIssueCount)} issues\n`;
|
|
if (issuesBySeverityMessage) {
|
|
totalIssues = `${chalk.bold(totalIssueCount)} issues: ${issuesBySeverityMessage}\n`;
|
|
}
|
|
}
|
|
const { count: fixableCount } = fixable_issues_1.hasFixableIssues(testResults);
|
|
const fixableIssues = fixableCount > 0 ? `${chalk.bold(fixableCount)} issues are fixable\n` : '';
|
|
const fixedIssueCount = calculateFixedIssues(resultsByPlugin);
|
|
const fixedIssuesSummary = fixedIssueCount > 0
|
|
? `${chalk.bold(fixedIssueCount)} issues were successfully fixed\n`
|
|
: '';
|
|
return `\n${exports.PADDING_SPACE}${totalIssues}${exports.PADDING_SPACE}${fixableIssues}${exports.PADDING_SPACE}${fixedIssuesSummary}`;
|
|
}
|
|
exports.generateIssueSummary = generateIssueSummary;
|
|
function getTestResults(resultsByPlugin, exceptionsByScanType) {
|
|
const testResults = [];
|
|
for (const plugin of Object.keys(resultsByPlugin)) {
|
|
const { skipped, failed, succeeded } = resultsByPlugin[plugin];
|
|
testResults.push(...skipped.map((i) => i.original.testResult));
|
|
testResults.push(...failed.map((i) => i.original.testResult));
|
|
testResults.push(...succeeded.map((i) => i.original.testResult));
|
|
}
|
|
if (Object.keys(exceptionsByScanType).length) {
|
|
for (const ecosystem of Object.keys(exceptionsByScanType)) {
|
|
const unresolved = exceptionsByScanType[ecosystem];
|
|
testResults.push(...unresolved.originals.map((i) => i.testResult));
|
|
}
|
|
}
|
|
return testResults;
|
|
}
|
|
exports.getTestResults = getTestResults;
|
|
//# sourceMappingURL=show-results-summary.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 24957:
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.partitionByVulnerable = void 0;
|
|
function partitionByVulnerable(entities) {
|
|
const vulnerable = [];
|
|
const notVulnerable = [];
|
|
for (const entity of entities) {
|
|
const hasIssues = entity.testResult.issues.length > 0;
|
|
if (hasIssues) {
|
|
vulnerable.push(entity);
|
|
}
|
|
else {
|
|
notVulnerable.push(entity);
|
|
}
|
|
}
|
|
return { vulnerable, notVulnerable };
|
|
}
|
|
exports.partitionByVulnerable = partitionByVulnerable;
|
|
//# sourceMappingURL=partition-by-vulnerable.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 65090:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.loadPlugin = void 0;
|
|
const unsupported_type_error_1 = __webpack_require__(90361);
|
|
const python_1 = __webpack_require__(97090);
|
|
function loadPlugin(type) {
|
|
switch (type) {
|
|
case 'pip': {
|
|
return python_1.pythonFix;
|
|
}
|
|
case 'poetry': {
|
|
return python_1.pythonFix;
|
|
}
|
|
default: {
|
|
throw new unsupported_type_error_1.UnsupportedTypeError(type);
|
|
}
|
|
}
|
|
}
|
|
exports.loadPlugin = loadPlugin;
|
|
//# sourceMappingURL=load-plugin.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 96377:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.checkPackageToolSupported = void 0;
|
|
const chalk = __webpack_require__(98250);
|
|
const pipenvPipfileFix = __webpack_require__(91989);
|
|
const poetryFix = __webpack_require__(69671);
|
|
const ora = __webpack_require__(63395);
|
|
const supportFunc = {
|
|
pipenv: {
|
|
isInstalled: () => pipenvPipfileFix.isPipenvInstalled(),
|
|
isSupportedVersion: (version) => pipenvPipfileFix.isPipenvSupportedVersion(version),
|
|
},
|
|
poetry: {
|
|
isInstalled: () => poetryFix.isPoetryInstalled(),
|
|
isSupportedVersion: (version) => poetryFix.isPoetrySupportedVersion(version),
|
|
},
|
|
};
|
|
async function checkPackageToolSupported(packageManager, options) {
|
|
const { version } = await supportFunc[packageManager].isInstalled();
|
|
const spinner = ora({ isSilent: options.quiet, stream: process.stdout });
|
|
spinner.clear();
|
|
spinner.text = `Checking ${packageManager} version`;
|
|
spinner.indent = 2;
|
|
spinner.start();
|
|
if (!version) {
|
|
spinner.stopAndPersist({
|
|
text: chalk.hex('#EDD55E')(`Could not detect ${packageManager} version, proceeding anyway. Some operations may fail.`),
|
|
symbol: chalk.hex('#EDD55E')('⚠️'),
|
|
});
|
|
return;
|
|
}
|
|
const { supported, versions } = supportFunc[packageManager].isSupportedVersion(version);
|
|
if (!supported) {
|
|
const spinnerMessage = ` ${version} ${packageManager} version detected. Currently the following ${packageManager} versions are supported: ${versions.join(',')}`;
|
|
spinner.stopAndPersist({
|
|
text: chalk.hex('#EDD55E')(spinnerMessage),
|
|
symbol: chalk.hex('#EDD55E')('⚠️'),
|
|
});
|
|
}
|
|
else {
|
|
spinner.stop();
|
|
}
|
|
}
|
|
exports.checkPackageToolSupported = checkPackageToolSupported;
|
|
//# sourceMappingURL=package-tool-supported.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 10774:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.isRequirementsTxtManifest = exports.getHandlerType = void 0;
|
|
const pathLib = __webpack_require__(85622);
|
|
const supported_handler_types_1 = __webpack_require__(56394);
|
|
function getHandlerType(entity) {
|
|
const targetFile = entity.scanResult.identity.targetFile;
|
|
if (!targetFile) {
|
|
return null;
|
|
}
|
|
const packageManagerOverride = entity.options.packageManager;
|
|
if (packageManagerOverride) {
|
|
return getTypeFromPackageManager(packageManagerOverride);
|
|
}
|
|
const path = pathLib.parse(targetFile);
|
|
if (isRequirementsTxtManifest(targetFile)) {
|
|
return supported_handler_types_1.SUPPORTED_HANDLER_TYPES.REQUIREMENTS;
|
|
}
|
|
else if (['Pipfile'].includes(path.base)) {
|
|
return supported_handler_types_1.SUPPORTED_HANDLER_TYPES.PIPFILE;
|
|
}
|
|
else if (['pyproject.toml', 'poetry.lock'].includes(path.base)) {
|
|
return supported_handler_types_1.SUPPORTED_HANDLER_TYPES.POETRY;
|
|
}
|
|
return null;
|
|
}
|
|
exports.getHandlerType = getHandlerType;
|
|
function isRequirementsTxtManifest(targetFile) {
|
|
return targetFile.endsWith('.txt');
|
|
}
|
|
exports.isRequirementsTxtManifest = isRequirementsTxtManifest;
|
|
function getTypeFromPackageManager(packageManager) {
|
|
switch (packageManager) {
|
|
case 'pip':
|
|
return supported_handler_types_1.SUPPORTED_HANDLER_TYPES.REQUIREMENTS;
|
|
case 'poetry':
|
|
return supported_handler_types_1.SUPPORTED_HANDLER_TYPES.POETRY;
|
|
default:
|
|
return null;
|
|
}
|
|
}
|
|
//# sourceMappingURL=get-handler-type.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 70145:
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.isSuccessfulChange = exports.generateSuccessfulChanges = exports.generateFailedChanges = void 0;
|
|
function generateFailedChanges(attemptedUpdates, pins, error, command) {
|
|
const changes = [];
|
|
for (const pkgAtVersion of Object.keys(pins)) {
|
|
const pin = pins[pkgAtVersion];
|
|
if (!attemptedUpdates
|
|
.map((update) => update.replace('==', '@'))
|
|
.includes(pin.upgradeTo)) {
|
|
continue;
|
|
}
|
|
const updatedMessage = pin.isTransitive ? 'pin' : 'upgrade';
|
|
const newVersion = pin.upgradeTo.split('@')[1];
|
|
const [pkgName, version] = pkgAtVersion.split('@');
|
|
changes.push({
|
|
success: false,
|
|
reason: error.message,
|
|
userMessage: `Failed to ${updatedMessage} ${pkgName} from ${version} to ${newVersion}`,
|
|
tip: command ? `Try running \`${command}\`` : undefined,
|
|
issueIds: pin.vulns,
|
|
from: pkgAtVersion,
|
|
to: `${pkgName}@${newVersion}`,
|
|
});
|
|
}
|
|
return changes;
|
|
}
|
|
exports.generateFailedChanges = generateFailedChanges;
|
|
function generateSuccessfulChanges(appliedUpgrades, pins) {
|
|
const changes = [];
|
|
for (const pkgAtVersion of Object.keys(pins)) {
|
|
const pin = pins[pkgAtVersion];
|
|
if (!appliedUpgrades
|
|
.map((upgrade) => upgrade.replace('==', '@'))
|
|
.includes(pin.upgradeTo)) {
|
|
continue;
|
|
}
|
|
const updatedMessage = pin.isTransitive ? 'Pinned' : 'Upgraded';
|
|
const newVersion = pin.upgradeTo.split('@')[1];
|
|
const [pkgName, version] = pkgAtVersion.split('@');
|
|
changes.push({
|
|
success: true,
|
|
userMessage: `${updatedMessage} ${pkgName} from ${version} to ${newVersion}`,
|
|
issueIds: pin.vulns,
|
|
from: pkgAtVersion,
|
|
to: `${pkgName}@${newVersion}`,
|
|
});
|
|
}
|
|
return changes;
|
|
}
|
|
exports.generateSuccessfulChanges = generateSuccessfulChanges;
|
|
function isSuccessfulChange(change) {
|
|
return change.success === true;
|
|
}
|
|
exports.isSuccessfulChange = isSuccessfulChange;
|
|
//# sourceMappingURL=attempted-changes-summary.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 60174:
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.partitionByFixable = exports.isSupported = exports.projectTypeSupported = void 0;
|
|
function projectTypeSupported(res) {
|
|
return !('reason' in res);
|
|
}
|
|
exports.projectTypeSupported = projectTypeSupported;
|
|
async function isSupported(entity) {
|
|
const remediationData = entity.testResult.remediation;
|
|
if (!remediationData) {
|
|
return { supported: false, reason: 'No remediation data available' };
|
|
}
|
|
if (!remediationData.pin || Object.keys(remediationData.pin).length === 0) {
|
|
return {
|
|
supported: false,
|
|
reason: 'There is no actionable remediation to apply',
|
|
};
|
|
}
|
|
return { supported: true };
|
|
}
|
|
exports.isSupported = isSupported;
|
|
async function partitionByFixable(entities) {
|
|
const fixable = [];
|
|
const skipped = [];
|
|
for (const entity of entities) {
|
|
const isSupportedResponse = await isSupported(entity);
|
|
if (projectTypeSupported(isSupportedResponse)) {
|
|
fixable.push(entity);
|
|
continue;
|
|
}
|
|
skipped.push({
|
|
original: entity,
|
|
userMessage: isSupportedResponse.reason,
|
|
});
|
|
}
|
|
return { fixable, skipped };
|
|
}
|
|
exports.partitionByFixable = partitionByFixable;
|
|
//# sourceMappingURL=is-supported.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 9744:
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.containsRequireDirective = void 0;
|
|
/* Requires like -r, -c are not supported at the moment, as multiple files
|
|
* would have to be identified and fixed together
|
|
* https://pip.pypa.io/en/stable/reference/pip_install/#options
|
|
*/
|
|
async function containsRequireDirective(requirementsTxt) {
|
|
const allMatches = [];
|
|
const REQUIRE_PATTERN = new RegExp(/^[^\S\n]*-(r|c)\s+(.+)/, 'gm');
|
|
const matches = getAllMatchedGroups(REQUIRE_PATTERN, requirementsTxt);
|
|
for (const match of matches) {
|
|
if (match && match.length > 1) {
|
|
allMatches.push(match);
|
|
}
|
|
}
|
|
return { containsRequire: allMatches.length > 0, matches: allMatches };
|
|
}
|
|
exports.containsRequireDirective = containsRequireDirective;
|
|
function getAllMatchedGroups(re, str) {
|
|
const groups = [];
|
|
let match;
|
|
while ((match = re.exec(str))) {
|
|
groups.push(match);
|
|
}
|
|
return groups;
|
|
}
|
|
//# sourceMappingURL=contains-require-directive.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 85844:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.extractProvenance = void 0;
|
|
const path = __webpack_require__(85622);
|
|
const debugLib = __webpack_require__(15158);
|
|
const requirements_file_parser_1 = __webpack_require__(67285);
|
|
const contains_require_directive_1 = __webpack_require__(9744);
|
|
const debug = debugLib('snyk-fix:python:extract-version-provenance');
|
|
async function extractProvenance(workspace, rootDir, dir, fileName, provenance = {}) {
|
|
const requirementsFileName = path.join(dir, fileName);
|
|
const requirementsTxt = await workspace.readFile(requirementsFileName);
|
|
// keep all provenance paths with `/` as a separator
|
|
const relativeTargetFileName = path
|
|
.normalize(path.relative(rootDir, requirementsFileName))
|
|
.replace(path.sep, '/');
|
|
provenance = {
|
|
...provenance,
|
|
[relativeTargetFileName]: requirements_file_parser_1.parseRequirementsFile(requirementsTxt),
|
|
};
|
|
const { containsRequire, matches } = await contains_require_directive_1.containsRequireDirective(requirementsTxt);
|
|
if (containsRequire) {
|
|
for (const match of matches) {
|
|
const requiredFilePath = match[2];
|
|
if (provenance[requiredFilePath]) {
|
|
debug('Detected recursive require directive, skipping');
|
|
continue;
|
|
}
|
|
const { dir: requireDir, base } = path.parse(path.join(dir, requiredFilePath));
|
|
provenance = {
|
|
...provenance,
|
|
...(await extractProvenance(workspace, rootDir, requireDir, base, provenance)),
|
|
};
|
|
}
|
|
}
|
|
return provenance;
|
|
}
|
|
exports.extractProvenance = extractProvenance;
|
|
//# sourceMappingURL=extract-version-provenance.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 81065:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.selectFileForPinning = exports.applyAllFixes = exports.fixIndividualRequirementsTxt = exports.pipRequirementsTxt = void 0;
|
|
const debugLib = __webpack_require__(15158);
|
|
const pathLib = __webpack_require__(85622);
|
|
const sortBy = __webpack_require__(58254);
|
|
const groupBy = __webpack_require__(20276);
|
|
const update_dependencies_1 = __webpack_require__(5860);
|
|
const no_fixes_applied_1 = __webpack_require__(80799);
|
|
const extract_version_provenance_1 = __webpack_require__(85844);
|
|
const requirements_file_parser_1 = __webpack_require__(67285);
|
|
const standardize_package_name_1 = __webpack_require__(78078);
|
|
const contains_require_directive_1 = __webpack_require__(9744);
|
|
const validate_required_data_1 = __webpack_require__(57894);
|
|
const format_display_name_1 = __webpack_require__(90686);
|
|
const debug = debugLib('snyk-fix:python:requirements.txt');
|
|
async function pipRequirementsTxt(fixable, options) {
|
|
debug(`Preparing to fix ${fixable.length} Python requirements.txt projects`);
|
|
const handlerResult = {
|
|
succeeded: [],
|
|
failed: [],
|
|
skipped: [],
|
|
};
|
|
const ordered = sortByDirectory(fixable);
|
|
let fixedFilesCache = {};
|
|
for (const dir of Object.keys(ordered)) {
|
|
debug(`Fixing entities in directory ${dir}`);
|
|
const entitiesPerDirectory = ordered[dir].map((e) => e.entity);
|
|
const { failed, succeeded, skipped, fixedCache } = await fixAll(entitiesPerDirectory, options, fixedFilesCache);
|
|
fixedFilesCache = {
|
|
...fixedFilesCache,
|
|
...fixedCache,
|
|
};
|
|
handlerResult.succeeded.push(...succeeded);
|
|
handlerResult.failed.push(...failed);
|
|
handlerResult.skipped.push(...skipped);
|
|
}
|
|
return handlerResult;
|
|
}
|
|
exports.pipRequirementsTxt = pipRequirementsTxt;
|
|
async function fixAll(entities, options, fixedCache) {
|
|
const handlerResult = {
|
|
succeeded: [],
|
|
failed: [],
|
|
skipped: [],
|
|
};
|
|
for (const entity of entities) {
|
|
const targetFile = entity.scanResult.identity.targetFile;
|
|
try {
|
|
const { dir, base } = pathLib.parse(targetFile);
|
|
// parse & join again to support correct separator
|
|
const filePath = pathLib.normalize(pathLib.join(dir, base));
|
|
if (Object.keys(fixedCache).includes(pathLib.normalize(pathLib.join(dir, base)))) {
|
|
handlerResult.succeeded.push({
|
|
original: entity,
|
|
changes: [
|
|
{
|
|
success: true,
|
|
userMessage: `Fixed through ${format_display_name_1.formatDisplayName(entity.workspace.path, {
|
|
type: entity.scanResult.identity.type,
|
|
targetFile: fixedCache[filePath].fixedIn,
|
|
})}`,
|
|
issueIds: getFixedEntityIssues(fixedCache[filePath].issueIds, entity.testResult.issues),
|
|
},
|
|
],
|
|
});
|
|
continue;
|
|
}
|
|
const { changes, fixedMeta } = await applyAllFixes(entity, options);
|
|
if (!changes.length) {
|
|
debug('Manifest has not changed!');
|
|
throw new no_fixes_applied_1.NoFixesCouldBeAppliedError();
|
|
}
|
|
// keep issues were successfully fixed unique across files that are part of the same project
|
|
// the test result is for 1 entry entity.
|
|
const uniqueIssueIds = new Set();
|
|
for (const c of changes) {
|
|
c.issueIds.map((i) => uniqueIssueIds.add(i));
|
|
}
|
|
Object.keys(fixedMeta).forEach((f) => {
|
|
fixedCache[f] = {
|
|
fixedIn: targetFile,
|
|
issueIds: Array.from(uniqueIssueIds),
|
|
};
|
|
});
|
|
handlerResult.succeeded.push({ original: entity, changes });
|
|
}
|
|
catch (e) {
|
|
debug(`Failed to fix ${targetFile}.\nERROR: ${e}`);
|
|
handlerResult.failed.push({ original: entity, error: e });
|
|
}
|
|
}
|
|
return { ...handlerResult, fixedCache };
|
|
}
|
|
// TODO: optionally verify the deps install
|
|
async function fixIndividualRequirementsTxt(workspace, dir, entryFileName, fileName, remediation, parsedRequirements, options, directUpgradesOnly) {
|
|
const entryFilePath = pathLib.normalize(pathLib.join(dir, entryFileName));
|
|
const fullFilePath = pathLib.normalize(pathLib.join(dir, fileName));
|
|
const { updatedManifest, changes } = update_dependencies_1.updateDependencies(parsedRequirements, remediation.pin, directUpgradesOnly, entryFilePath !== fullFilePath
|
|
? format_display_name_1.formatDisplayName(workspace.path, {
|
|
type: 'pip',
|
|
targetFile: fullFilePath,
|
|
})
|
|
: undefined);
|
|
if (!changes.length) {
|
|
return { changes };
|
|
}
|
|
if (!options.dryRun) {
|
|
debug('Writing changes to file');
|
|
await workspace.writeFile(pathLib.join(dir, fileName), updatedManifest);
|
|
}
|
|
else {
|
|
debug('Skipping writing changes to file in --dry-run mode');
|
|
}
|
|
return { changes };
|
|
}
|
|
exports.fixIndividualRequirementsTxt = fixIndividualRequirementsTxt;
|
|
async function applyAllFixes(entity, options) {
|
|
const { remediation, targetFile: entryFileName, workspace, } = validate_required_data_1.validateRequiredData(entity);
|
|
const fixedMeta = {};
|
|
const { dir, base } = pathLib.parse(entryFileName);
|
|
const provenance = await extract_version_provenance_1.extractProvenance(workspace, dir, dir, base);
|
|
const upgradeChanges = [];
|
|
/* Apply all upgrades first across all files that are included */
|
|
for (const fileName of Object.keys(provenance)) {
|
|
const skipApplyingPins = true;
|
|
const { changes } = await fixIndividualRequirementsTxt(workspace, dir, base, fileName, remediation, provenance[fileName], options, skipApplyingPins);
|
|
upgradeChanges.push(...changes);
|
|
fixedMeta[pathLib.normalize(pathLib.join(dir, fileName))] = upgradeChanges;
|
|
}
|
|
/* Apply all left over remediation as pins in the entry targetFile */
|
|
const toPin = filterOutAppliedUpgrades(remediation, upgradeChanges);
|
|
const directUpgradesOnly = false;
|
|
const fileForPinning = await selectFileForPinning(entity);
|
|
const { changes: pinnedChanges } = await fixIndividualRequirementsTxt(workspace, dir, base, fileForPinning.fileName, toPin, requirements_file_parser_1.parseRequirementsFile(fileForPinning.fileContent), options, directUpgradesOnly);
|
|
return { changes: [...upgradeChanges, ...pinnedChanges], fixedMeta };
|
|
}
|
|
exports.applyAllFixes = applyAllFixes;
|
|
function filterOutAppliedUpgrades(remediation, upgradeChanges) {
|
|
const pinRemediation = {
|
|
...remediation,
|
|
pin: {},
|
|
};
|
|
const pins = remediation.pin;
|
|
const normalizedAppliedRemediation = upgradeChanges
|
|
.map((c) => {
|
|
var _a;
|
|
if (c.success && c.from) {
|
|
const [pkgName, versionAndMore] = (_a = c.from) === null || _a === void 0 ? void 0 : _a.split('@');
|
|
return `${standardize_package_name_1.standardizePackageName(pkgName)}@${versionAndMore}`;
|
|
}
|
|
return false;
|
|
})
|
|
.filter(Boolean);
|
|
for (const pkgAtVersion of Object.keys(pins)) {
|
|
const [pkgName, versionAndMore] = pkgAtVersion.split('@');
|
|
if (!normalizedAppliedRemediation.includes(`${standardize_package_name_1.standardizePackageName(pkgName)}@${versionAndMore}`)) {
|
|
pinRemediation.pin[pkgAtVersion] = pins[pkgAtVersion];
|
|
}
|
|
}
|
|
return pinRemediation;
|
|
}
|
|
function sortByDirectory(entities) {
|
|
const mapped = entities.map((e) => ({
|
|
entity: e,
|
|
...pathLib.parse(e.scanResult.identity.targetFile),
|
|
}));
|
|
const sorted = sortBy(mapped, 'dir');
|
|
return groupBy(sorted, 'dir');
|
|
}
|
|
async function selectFileForPinning(entity) {
|
|
const targetFile = entity.scanResult.identity.targetFile;
|
|
const { dir, base } = pathLib.parse(targetFile);
|
|
const { workspace } = entity;
|
|
// default to adding pins in the scanned file
|
|
let fileName = base;
|
|
let requirementsTxt = await workspace.readFile(targetFile);
|
|
const { containsRequire, matches } = await contains_require_directive_1.containsRequireDirective(requirementsTxt);
|
|
const constraintsMatch = matches.filter((m) => m.includes('c'));
|
|
if (containsRequire && constraintsMatch[0]) {
|
|
// prefer to pin in constraints file if present
|
|
fileName = constraintsMatch[0][2];
|
|
requirementsTxt = await workspace.readFile(pathLib.join(dir, fileName));
|
|
}
|
|
return { fileContent: requirementsTxt, fileName };
|
|
}
|
|
exports.selectFileForPinning = selectFileForPinning;
|
|
function getFixedEntityIssues(fixedIssueIds, issues) {
|
|
const fixed = [];
|
|
for (const { issueId } of issues) {
|
|
if (fixedIssueIds.includes(issueId)) {
|
|
fixed.push(issueId);
|
|
}
|
|
}
|
|
return fixed;
|
|
}
|
|
//# sourceMappingURL=index.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 57584:
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.applyUpgrades = void 0;
|
|
function applyUpgrades(originalRequirements, upgradedRequirements) {
|
|
const updated = [];
|
|
for (const requirement of originalRequirements) {
|
|
const { originalText } = requirement;
|
|
if (upgradedRequirements[originalText]) {
|
|
updated.push(upgradedRequirements[originalText]);
|
|
}
|
|
else {
|
|
updated.push(originalText);
|
|
}
|
|
}
|
|
return updated;
|
|
}
|
|
exports.applyUpgrades = applyUpgrades;
|
|
//# sourceMappingURL=apply-upgrades.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 40853:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.calculateRelevantFixes = void 0;
|
|
const is_defined_1 = __webpack_require__(38122);
|
|
const standardize_package_name_1 = __webpack_require__(78078);
|
|
function calculateRelevantFixes(requirements, updates, type) {
|
|
const lowerCasedUpdates = {};
|
|
const topLevelDeps = requirements.map(({ name }) => name).filter(is_defined_1.isDefined);
|
|
Object.keys(updates).forEach((update) => {
|
|
const { upgradeTo } = updates[update];
|
|
const [pkgName] = update.split('@');
|
|
const isTransitive = topLevelDeps.indexOf(standardize_package_name_1.standardizePackageName(pkgName)) < 0;
|
|
if (type === 'transitive-pins' ? isTransitive : !isTransitive) {
|
|
const [name, newVersion] = upgradeTo.split('@');
|
|
lowerCasedUpdates[update] = {
|
|
...updates[update],
|
|
upgradeTo: `${standardize_package_name_1.standardizePackageName(name)}@${newVersion}`,
|
|
};
|
|
}
|
|
});
|
|
return lowerCasedUpdates;
|
|
}
|
|
exports.calculateRelevantFixes = calculateRelevantFixes;
|
|
//# sourceMappingURL=calculate-relevant-fixes.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 2694:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.generatePins = void 0;
|
|
const calculate_relevant_fixes_1 = __webpack_require__(40853);
|
|
const is_defined_1 = __webpack_require__(38122);
|
|
const standardize_package_name_1 = __webpack_require__(78078);
|
|
function generatePins(requirements, updates, referenceFileInChanges) {
|
|
// Lowercase the upgrades object. This might be overly defensive, given that
|
|
// we control this input internally, but its a low cost guard rail. Outputs a
|
|
// mapping of upgrade to -> from, instead of the nested upgradeTo object.
|
|
const standardizedPins = calculate_relevant_fixes_1.calculateRelevantFixes(requirements, updates, 'transitive-pins');
|
|
if (Object.keys(standardizedPins).length === 0) {
|
|
return {
|
|
pinnedRequirements: [],
|
|
changes: [],
|
|
};
|
|
}
|
|
const changes = [];
|
|
const pinnedRequirements = Object.keys(standardizedPins)
|
|
.map((pkgNameAtVersion) => {
|
|
const [pkgName, version] = pkgNameAtVersion.split('@');
|
|
const newVersion = standardizedPins[pkgNameAtVersion].upgradeTo.split('@')[1];
|
|
const newRequirement = `${standardize_package_name_1.standardizePackageName(pkgName)}>=${newVersion}`;
|
|
changes.push({
|
|
from: `${pkgName}@${version}`,
|
|
to: `${pkgName}@${newVersion}`,
|
|
issueIds: standardizedPins[pkgNameAtVersion].vulns,
|
|
success: true,
|
|
userMessage: `Pinned ${standardize_package_name_1.standardizePackageName(pkgName)} from ${version} to ${newVersion}${referenceFileInChanges ? ` (pinned in ${referenceFileInChanges})` : ''}`,
|
|
});
|
|
return `${newRequirement} # not directly required, pinned by Snyk to avoid a vulnerability`;
|
|
})
|
|
.filter(is_defined_1.isDefined);
|
|
return {
|
|
pinnedRequirements,
|
|
changes,
|
|
};
|
|
}
|
|
exports.generatePins = generatePins;
|
|
//# sourceMappingURL=generate-pins.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 86047:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.generateUpgrades = void 0;
|
|
const standardize_package_name_1 = __webpack_require__(78078);
|
|
const calculate_relevant_fixes_1 = __webpack_require__(40853);
|
|
function generateUpgrades(requirements, updates, referenceFileInChanges) {
|
|
// Lowercase the upgrades object. This might be overly defensive, given that
|
|
// we control this input internally, but its a low cost guard rail. Outputs a
|
|
// mapping of upgrade to -> from, instead of the nested upgradeTo object.
|
|
const normalizedUpgrades = calculate_relevant_fixes_1.calculateRelevantFixes(requirements, updates, 'direct-upgrades');
|
|
if (Object.keys(normalizedUpgrades).length === 0) {
|
|
return {
|
|
updatedRequirements: {},
|
|
changes: [],
|
|
};
|
|
}
|
|
const changes = [];
|
|
const updatedRequirements = {};
|
|
requirements.map(({ name, originalName, versionComparator, version, originalText, extras, }) => {
|
|
// Defensive patching; if any of these are undefined, return
|
|
if (typeof name === 'undefined' ||
|
|
typeof versionComparator === 'undefined' ||
|
|
typeof version === 'undefined' ||
|
|
originalText === '') {
|
|
return;
|
|
}
|
|
// Check if we have an upgrade; if we do, replace the version string with
|
|
// the upgrade, but keep the rest of the content
|
|
const upgrade = Object.keys(normalizedUpgrades).filter((packageVersionUpgrade) => {
|
|
const [pkgName, versionAndMore] = packageVersionUpgrade.split('@');
|
|
return `${standardize_package_name_1.standardizePackageName(pkgName)}@${versionAndMore}`.startsWith(`${standardize_package_name_1.standardizePackageName(name)}@${version}`);
|
|
})[0];
|
|
if (!upgrade) {
|
|
return;
|
|
}
|
|
const newVersion = normalizedUpgrades[upgrade].upgradeTo.split('@')[1];
|
|
const updatedRequirement = `${originalName}${versionComparator}${newVersion}`;
|
|
changes.push({
|
|
issueIds: normalizedUpgrades[upgrade].vulns,
|
|
from: `${originalName}@${version}`,
|
|
to: `${originalName}@${newVersion}`,
|
|
success: true,
|
|
userMessage: `Upgraded ${originalName} from ${version} to ${newVersion}${referenceFileInChanges
|
|
? ` (upgraded in ${referenceFileInChanges})`
|
|
: ''}`,
|
|
});
|
|
updatedRequirements[originalText] = `${updatedRequirement}${extras ? extras : ''}`;
|
|
});
|
|
return {
|
|
updatedRequirements,
|
|
changes,
|
|
};
|
|
}
|
|
exports.generateUpgrades = generateUpgrades;
|
|
//# sourceMappingURL=generate-upgrades.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 5860:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.updateDependencies = void 0;
|
|
const debugLib = __webpack_require__(15158);
|
|
const generate_pins_1 = __webpack_require__(2694);
|
|
const apply_upgrades_1 = __webpack_require__(57584);
|
|
const generate_upgrades_1 = __webpack_require__(86047);
|
|
const failed_to_parse_manifest_1 = __webpack_require__(84657);
|
|
const debug = debugLib('snyk-fix:python:update-dependencies');
|
|
/*
|
|
* Given contents of manifest file(s) and a set of upgrades, apply the given
|
|
* upgrades to a manifest and return the upgraded manifest.
|
|
*
|
|
* Currently only supported for `requirements.txt` - at least one file named
|
|
* `requirements.txt` must be in the manifests.
|
|
*/
|
|
function updateDependencies(parsedRequirementsData, updates, directUpgradesOnly = false, referenceFileInChanges) {
|
|
const { requirements, endsWithNewLine: shouldEndWithNewLine, } = parsedRequirementsData;
|
|
if (!requirements.length) {
|
|
debug('Error: Expected to receive parsed manifest data. Is manifest empty?');
|
|
throw new failed_to_parse_manifest_1.FailedToParseManifest();
|
|
}
|
|
debug('Finished parsing manifest');
|
|
const { updatedRequirements, changes: upgradedChanges } = generate_upgrades_1.generateUpgrades(requirements, updates, referenceFileInChanges);
|
|
debug('Finished generating upgrades to apply');
|
|
let pinnedRequirements = [];
|
|
let pinChanges = [];
|
|
if (!directUpgradesOnly) {
|
|
({ pinnedRequirements, changes: pinChanges } = generate_pins_1.generatePins(requirements, updates, referenceFileInChanges));
|
|
debug('Finished generating pins to apply');
|
|
}
|
|
let updatedManifest = [
|
|
...apply_upgrades_1.applyUpgrades(requirements, updatedRequirements),
|
|
...pinnedRequirements,
|
|
].join('\n');
|
|
// This is a bit of a hack, but an easy one to follow. If a file ends with a
|
|
// new line, ensure we keep it this way. Don't hijack customers formatting.
|
|
if (shouldEndWithNewLine) {
|
|
updatedManifest += '\n';
|
|
}
|
|
debug('Finished applying changes to manifest');
|
|
return {
|
|
updatedManifest,
|
|
changes: [...pinChanges, ...upgradedChanges],
|
|
};
|
|
}
|
|
exports.updateDependencies = updateDependencies;
|
|
//# sourceMappingURL=index.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 38122:
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.isDefined = void 0;
|
|
// TS is not capable of determining when Array.filter has removed undefined
|
|
// values without a manual Type Guard, so thats what this does
|
|
function isDefined(t) {
|
|
return typeof t !== 'undefined';
|
|
}
|
|
exports.isDefined = isDefined;
|
|
//# sourceMappingURL=is-defined.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 67285:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.parseRequirementsFile = void 0;
|
|
const debugLib = __webpack_require__(15158);
|
|
const standardize_package_name_1 = __webpack_require__(78078);
|
|
const debug = debugLib('snyk-fix:python:requirements-file-parser');
|
|
function parseRequirementsFile(requirementsFile) {
|
|
const endsWithNewLine = requirementsFile.endsWith('\n');
|
|
const lines = requirementsFile.replace(/\n$/, '').split('\n');
|
|
const requirements = [];
|
|
lines.map((requirementText, line) => {
|
|
const requirement = extractDependencyDataFromLine(requirementText, line);
|
|
if (requirement) {
|
|
requirements.push(requirement);
|
|
}
|
|
});
|
|
return { requirements, endsWithNewLine };
|
|
}
|
|
exports.parseRequirementsFile = parseRequirementsFile;
|
|
function extractDependencyDataFromLine(requirementText, line) {
|
|
try {
|
|
const requirement = { originalText: requirementText, line };
|
|
const trimmedText = requirementText.trim();
|
|
// Quick returns for cases we cannot remediate
|
|
// - Empty line i.e. ''
|
|
// - 'editable' packages i.e. '-e git://git.myproject.org/MyProject.git#egg=MyProject'
|
|
// - Comments i.e. # This is a comment
|
|
// - Local files i.e. file:../../lib/project#egg=MyProject
|
|
if (requirementText === '' ||
|
|
trimmedText.startsWith('-e') ||
|
|
trimmedText.startsWith('#') ||
|
|
trimmedText.startsWith('file:')) {
|
|
return requirement;
|
|
}
|
|
// Regex to match against a Python package specifier. Any invalid lines (or
|
|
// lines we can't handle) should have been returned this point.
|
|
const regex = /([A-Z0-9-._]*)(!=|===|==|>=|<=|>|<|~=)(\d*\.?\d*\.?\d*[A-Z0-9]*)(.*)/i;
|
|
const result = regex.exec(requirementText);
|
|
if (result !== null) {
|
|
requirement.name = standardize_package_name_1.standardizePackageName(result[1]);
|
|
requirement.originalName = result[1];
|
|
requirement.versionComparator = result[2];
|
|
requirement.version = result[3];
|
|
requirement.extras = result[4];
|
|
}
|
|
if (!(requirement.version && requirement.name)) {
|
|
throw new Error('Failed to extract dependency data');
|
|
}
|
|
return requirement;
|
|
}
|
|
catch (err) {
|
|
debug({ error: err.message, requirementText, line }, 'failed to parse requirement');
|
|
return { originalText: requirementText, line };
|
|
}
|
|
}
|
|
//# sourceMappingURL=requirements-file-parser.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 28006:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.pipenvPipfile = void 0;
|
|
const debugLib = __webpack_require__(15158);
|
|
const ora = __webpack_require__(63395);
|
|
const package_tool_supported_1 = __webpack_require__(96377);
|
|
const update_dependencies_1 = __webpack_require__(21110);
|
|
const debug = debugLib('snyk-fix:python:Pipfile');
|
|
async function pipenvPipfile(fixable, options) {
|
|
debug(`Preparing to fix ${fixable.length} Python Pipfile projects`);
|
|
const handlerResult = {
|
|
succeeded: [],
|
|
failed: [],
|
|
skipped: [],
|
|
};
|
|
await package_tool_supported_1.checkPackageToolSupported('pipenv', options);
|
|
for (const [index, entity] of fixable.entries()) {
|
|
const spinner = ora({ isSilent: options.quiet, stream: process.stdout });
|
|
const spinnerMessage = `Fixing Pipfile ${index + 1}/${fixable.length}`;
|
|
spinner.text = spinnerMessage;
|
|
spinner.start();
|
|
const { failed, succeeded, skipped } = await update_dependencies_1.updateDependencies(entity, options);
|
|
handlerResult.succeeded.push(...succeeded);
|
|
handlerResult.failed.push(...failed);
|
|
handlerResult.skipped.push(...skipped);
|
|
spinner.stop();
|
|
}
|
|
return handlerResult;
|
|
}
|
|
exports.pipenvPipfile = pipenvPipfile;
|
|
//# sourceMappingURL=index.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 13755:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.generateUpgrades = void 0;
|
|
const standardize_package_name_1 = __webpack_require__(78078);
|
|
const validate_required_data_1 = __webpack_require__(57894);
|
|
function generateUpgrades(entity) {
|
|
const { remediation } = validate_required_data_1.validateRequiredData(entity);
|
|
const { pin: pins } = remediation;
|
|
const upgrades = [];
|
|
for (const pkgAtVersion of Object.keys(pins)) {
|
|
const pin = pins[pkgAtVersion];
|
|
const newVersion = pin.upgradeTo.split('@')[1];
|
|
const [pkgName] = pkgAtVersion.split('@');
|
|
upgrades.push(`${standardize_package_name_1.standardizePackageName(pkgName)}==${newVersion}`);
|
|
}
|
|
return { upgrades };
|
|
}
|
|
exports.generateUpgrades = generateUpgrades;
|
|
//# sourceMappingURL=generate-upgrades.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 21110:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.updateDependencies = void 0;
|
|
const debugLib = __webpack_require__(15158);
|
|
const no_fixes_applied_1 = __webpack_require__(80799);
|
|
const generate_upgrades_1 = __webpack_require__(13755);
|
|
const pipenv_add_1 = __webpack_require__(22629);
|
|
const attempted_changes_summary_1 = __webpack_require__(70145);
|
|
const debug = debugLib('snyk-fix:python:Pipfile');
|
|
function chooseFixStrategy(options) {
|
|
return options.sequentialFix ? fixSequentially : fixAll;
|
|
}
|
|
async function updateDependencies(entity, options) {
|
|
const handlerResult = await chooseFixStrategy(options)(entity, options);
|
|
return handlerResult;
|
|
}
|
|
exports.updateDependencies = updateDependencies;
|
|
async function fixAll(entity, options) {
|
|
const handlerResult = {
|
|
succeeded: [],
|
|
failed: [],
|
|
skipped: [],
|
|
};
|
|
const changes = [];
|
|
try {
|
|
const { upgrades } = await generate_upgrades_1.generateUpgrades(entity);
|
|
if (!upgrades.length) {
|
|
throw new no_fixes_applied_1.NoFixesCouldBeAppliedError('Failed to calculate package updates to apply');
|
|
}
|
|
// TODO: for better support we need to:
|
|
// 1. parse the manifest and extract original requirements, version spec etc
|
|
// 2. swap out only the version and retain original spec
|
|
// 3. re-lock the lockfile
|
|
// Currently this is not possible as there is no Pipfile parser that would do this.
|
|
// update prod dependencies first
|
|
if (upgrades.length) {
|
|
changes.push(...(await pipenv_add_1.pipenvAdd(entity, options, upgrades)));
|
|
}
|
|
if (!changes.length) {
|
|
throw new no_fixes_applied_1.NoFixesCouldBeAppliedError();
|
|
}
|
|
if (!changes.some((c) => attempted_changes_summary_1.isSuccessfulChange(c))) {
|
|
handlerResult.failed.push({
|
|
original: entity,
|
|
changes,
|
|
});
|
|
}
|
|
else {
|
|
handlerResult.succeeded.push({
|
|
original: entity,
|
|
changes,
|
|
});
|
|
}
|
|
}
|
|
catch (error) {
|
|
debug(`Failed to fix ${entity.scanResult.identity.targetFile}.\nERROR: ${error}`);
|
|
handlerResult.failed.push({
|
|
original: entity,
|
|
error,
|
|
tip: error.tip,
|
|
});
|
|
}
|
|
return handlerResult;
|
|
}
|
|
async function fixSequentially(entity, options) {
|
|
const handlerResult = {
|
|
succeeded: [],
|
|
failed: [],
|
|
skipped: [],
|
|
};
|
|
const { upgrades } = await generate_upgrades_1.generateUpgrades(entity);
|
|
// TODO: for better support we need to:
|
|
// 1. parse the manifest and extract original requirements, version spec etc
|
|
// 2. swap out only the version and retain original spec
|
|
// 3. re-lock the lockfile
|
|
// at the moment we do not parse Pipfile and therefore can't tell the difference
|
|
// between prod & dev updates
|
|
const changes = [];
|
|
try {
|
|
if (!upgrades.length) {
|
|
throw new no_fixes_applied_1.NoFixesCouldBeAppliedError('Failed to calculate package updates to apply');
|
|
}
|
|
// update prod dependencies first
|
|
if (upgrades.length) {
|
|
for (const upgrade of upgrades) {
|
|
changes.push(...(await pipenv_add_1.pipenvAdd(entity, options, [upgrade])));
|
|
}
|
|
}
|
|
if (!changes.length) {
|
|
throw new no_fixes_applied_1.NoFixesCouldBeAppliedError();
|
|
}
|
|
if (!changes.some((c) => attempted_changes_summary_1.isSuccessfulChange(c))) {
|
|
handlerResult.failed.push({
|
|
original: entity,
|
|
changes,
|
|
});
|
|
}
|
|
else {
|
|
handlerResult.succeeded.push({
|
|
original: entity,
|
|
changes,
|
|
});
|
|
}
|
|
}
|
|
catch (error) {
|
|
debug(`Failed to fix ${entity.scanResult.identity.targetFile}.\nERROR: ${error}`);
|
|
handlerResult.failed.push({
|
|
original: entity,
|
|
tip: error.tip,
|
|
error,
|
|
});
|
|
}
|
|
return handlerResult;
|
|
}
|
|
//# sourceMappingURL=index.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 22629:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.pipenvAdd = void 0;
|
|
const pathLib = __webpack_require__(85622);
|
|
const pipenvPipfileFix = __webpack_require__(91989);
|
|
const debugLib = __webpack_require__(15158);
|
|
const validate_required_data_1 = __webpack_require__(57894);
|
|
const attempted_changes_summary_1 = __webpack_require__(70145);
|
|
const command_failed_to_run_error_1 = __webpack_require__(72353);
|
|
const no_fixes_applied_1 = __webpack_require__(80799);
|
|
const debug = debugLib('snyk-fix:python:pipenvAdd');
|
|
async function pipenvAdd(entity, options, upgrades) {
|
|
const changes = [];
|
|
let pipenvCommand;
|
|
const { remediation, targetFile } = validate_required_data_1.validateRequiredData(entity);
|
|
try {
|
|
const targetFilePath = pathLib.resolve(entity.workspace.path, targetFile);
|
|
const { dir } = pathLib.parse(targetFilePath);
|
|
if (!options.dryRun && upgrades.length) {
|
|
const { stderr, stdout, command, exitCode, } = await pipenvPipfileFix.pipenvInstall(dir, upgrades, {
|
|
python: entity.options.command,
|
|
});
|
|
debug('`pipenv add` returned:', { stderr, stdout, command });
|
|
if (exitCode !== 0) {
|
|
pipenvCommand = command;
|
|
throwPipenvError(stderr, stdout, command);
|
|
}
|
|
}
|
|
changes.push(...attempted_changes_summary_1.generateSuccessfulChanges(upgrades, remediation.pin));
|
|
}
|
|
catch (error) {
|
|
changes.push(...attempted_changes_summary_1.generateFailedChanges(upgrades, remediation.pin, error, pipenvCommand));
|
|
}
|
|
return changes;
|
|
}
|
|
exports.pipenvAdd = pipenvAdd;
|
|
function throwPipenvError(stderr, stdout, command) {
|
|
const incompatibleDeps = 'There are incompatible versions in the resolved dependencies';
|
|
const lockingFailed = 'Locking failed';
|
|
const versionNotFound = 'Could not find a version that matches';
|
|
const errorsToBubbleUp = [incompatibleDeps, lockingFailed, versionNotFound];
|
|
for (const error of errorsToBubbleUp) {
|
|
if (stderr.toLowerCase().includes(error.toLowerCase()) ||
|
|
stdout.toLowerCase().includes(error.toLowerCase())) {
|
|
throw new command_failed_to_run_error_1.CommandFailedError(error, command);
|
|
}
|
|
}
|
|
const SOLVER_PROBLEM = /SolverProblemError(.* version solving failed)/gms;
|
|
const solverProblemError = SOLVER_PROBLEM.exec(stderr) || SOLVER_PROBLEM.exec(stdout);
|
|
if (solverProblemError) {
|
|
throw new command_failed_to_run_error_1.CommandFailedError(solverProblemError[0].trim(), command);
|
|
}
|
|
throw new no_fixes_applied_1.NoFixesCouldBeAppliedError();
|
|
}
|
|
//# sourceMappingURL=pipenv-add.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 60428:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.poetry = void 0;
|
|
const debugLib = __webpack_require__(15158);
|
|
const ora = __webpack_require__(63395);
|
|
const package_tool_supported_1 = __webpack_require__(96377);
|
|
const update_dependencies_1 = __webpack_require__(61526);
|
|
const debug = debugLib('snyk-fix:python:Poetry');
|
|
async function poetry(fixable, options) {
|
|
debug(`Preparing to fix ${fixable.length} Python Poetry projects`);
|
|
const handlerResult = {
|
|
succeeded: [],
|
|
failed: [],
|
|
skipped: [],
|
|
};
|
|
await package_tool_supported_1.checkPackageToolSupported('poetry', options);
|
|
for (const [index, entity] of fixable.entries()) {
|
|
const spinner = ora({ isSilent: options.quiet, stream: process.stdout });
|
|
const spinnerMessage = `Fixing pyproject.toml ${index + 1}/${fixable.length}`;
|
|
spinner.text = spinnerMessage;
|
|
spinner.start();
|
|
const { failed, succeeded, skipped } = await update_dependencies_1.updateDependencies(entity, options);
|
|
handlerResult.succeeded.push(...succeeded);
|
|
handlerResult.failed.push(...failed);
|
|
handlerResult.skipped.push(...skipped);
|
|
spinner.stop();
|
|
}
|
|
return handlerResult;
|
|
}
|
|
exports.poetry = poetry;
|
|
//# sourceMappingURL=index.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 84204:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.generateUpgrades = void 0;
|
|
const pathLib = __webpack_require__(85622);
|
|
const toml = __webpack_require__(35424);
|
|
const debugLib = __webpack_require__(15158);
|
|
const validate_required_data_1 = __webpack_require__(57894);
|
|
const standardize_package_name_1 = __webpack_require__(78078);
|
|
const debug = debugLib('snyk-fix:python:Poetry');
|
|
async function generateUpgrades(entity) {
|
|
var _a, _b;
|
|
const { remediation, targetFile } = validate_required_data_1.validateRequiredData(entity);
|
|
const pins = remediation.pin;
|
|
const targetFilePath = pathLib.resolve(entity.workspace.path, targetFile);
|
|
const { dir } = pathLib.parse(targetFilePath);
|
|
const pyProjectTomlRaw = await entity.workspace.readFile(pathLib.resolve(dir, 'pyproject.toml'));
|
|
const pyProjectToml = toml.parse(pyProjectTomlRaw);
|
|
const prodTopLevelDeps = Object.keys((_a = pyProjectToml.tool.poetry.dependencies) !== null && _a !== void 0 ? _a : {}).map((dep) => standardize_package_name_1.standardizePackageName(dep));
|
|
const devTopLevelDeps = Object.keys((_b = pyProjectToml.tool.poetry['dev-dependencies']) !== null && _b !== void 0 ? _b : {}).map((dep) => standardize_package_name_1.standardizePackageName(dep));
|
|
const upgrades = [];
|
|
const devUpgrades = [];
|
|
for (const pkgAtVersion of Object.keys(pins)) {
|
|
const pin = pins[pkgAtVersion];
|
|
const newVersion = pin.upgradeTo.split('@')[1];
|
|
const [pkgName] = pkgAtVersion.split('@');
|
|
const upgrade = `${standardize_package_name_1.standardizePackageName(pkgName)}==${newVersion}`;
|
|
if (pin.isTransitive || prodTopLevelDeps.includes(pkgName)) {
|
|
// transitive and it could have come from a dev or prod dep
|
|
// since we can't tell right now let be pinned into production deps
|
|
upgrades.push(upgrade);
|
|
}
|
|
else if (prodTopLevelDeps.includes(pkgName)) {
|
|
upgrades.push(upgrade);
|
|
}
|
|
else if (entity.options.dev && devTopLevelDeps.includes(pkgName)) {
|
|
devUpgrades.push(upgrade);
|
|
}
|
|
else {
|
|
debug(`Could not determine what type of upgrade ${upgrade} is. When choosing between: transitive upgrade, production or dev direct upgrade. `);
|
|
}
|
|
}
|
|
return { upgrades, devUpgrades };
|
|
}
|
|
exports.generateUpgrades = generateUpgrades;
|
|
//# sourceMappingURL=generate-upgrades.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 61526:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.updateDependencies = void 0;
|
|
const debugLib = __webpack_require__(15158);
|
|
const generate_upgrades_1 = __webpack_require__(84204);
|
|
const poetry_add_1 = __webpack_require__(24881);
|
|
const no_fixes_applied_1 = __webpack_require__(80799);
|
|
const attempted_changes_summary_1 = __webpack_require__(70145);
|
|
const debug = debugLib('snyk-fix:python:Poetry');
|
|
function chooseFixStrategy(options) {
|
|
return options.sequentialFix ? fixSequentially : fixAll;
|
|
}
|
|
async function updateDependencies(entity, options) {
|
|
const handlerResult = await chooseFixStrategy(options)(entity, options);
|
|
return handlerResult;
|
|
}
|
|
exports.updateDependencies = updateDependencies;
|
|
async function fixAll(entity, options) {
|
|
const handlerResult = {
|
|
succeeded: [],
|
|
failed: [],
|
|
skipped: [],
|
|
};
|
|
const { upgrades, devUpgrades } = await generate_upgrades_1.generateUpgrades(entity);
|
|
// TODO: for better support we need to:
|
|
// 1. parse the manifest and extract original requirements, version spec etc
|
|
// 2. swap out only the version and retain original spec
|
|
// 3. re-lock the lockfile
|
|
const changes = [];
|
|
try {
|
|
if (![...upgrades, ...devUpgrades].length) {
|
|
throw new no_fixes_applied_1.NoFixesCouldBeAppliedError('Failed to calculate package updates to apply');
|
|
}
|
|
// update prod dependencies first
|
|
if (upgrades.length) {
|
|
changes.push(...(await poetry_add_1.poetryAdd(entity, options, upgrades)));
|
|
}
|
|
// update dev dependencies second
|
|
if (devUpgrades.length) {
|
|
const installDev = true;
|
|
changes.push(...(await poetry_add_1.poetryAdd(entity, options, devUpgrades, installDev)));
|
|
}
|
|
if (!changes.length) {
|
|
throw new no_fixes_applied_1.NoFixesCouldBeAppliedError();
|
|
}
|
|
if (!changes.some((c) => attempted_changes_summary_1.isSuccessfulChange(c))) {
|
|
handlerResult.failed.push({
|
|
original: entity,
|
|
changes,
|
|
});
|
|
}
|
|
else {
|
|
handlerResult.succeeded.push({
|
|
original: entity,
|
|
changes,
|
|
});
|
|
}
|
|
}
|
|
catch (error) {
|
|
debug(`Failed to fix ${entity.scanResult.identity.targetFile}.\nERROR: ${error}`);
|
|
handlerResult.failed.push({
|
|
original: entity,
|
|
tip: error.tip,
|
|
error,
|
|
});
|
|
}
|
|
return handlerResult;
|
|
}
|
|
async function fixSequentially(entity, options) {
|
|
const handlerResult = {
|
|
succeeded: [],
|
|
failed: [],
|
|
skipped: [],
|
|
};
|
|
const { upgrades, devUpgrades } = await generate_upgrades_1.generateUpgrades(entity);
|
|
// TODO: for better support we need to:
|
|
// 1. parse the manifest and extract original requirements, version spec etc
|
|
// 2. swap out only the version and retain original spec
|
|
// 3. re-lock the lockfile
|
|
const changes = [];
|
|
try {
|
|
if (![...upgrades, ...devUpgrades].length) {
|
|
throw new no_fixes_applied_1.NoFixesCouldBeAppliedError('Failed to calculate package updates to apply');
|
|
}
|
|
// update prod dependencies first
|
|
if (upgrades.length) {
|
|
for (const upgrade of upgrades) {
|
|
changes.push(...(await poetry_add_1.poetryAdd(entity, options, [upgrade])));
|
|
}
|
|
}
|
|
// update dev dependencies second
|
|
if (devUpgrades.length) {
|
|
for (const upgrade of devUpgrades) {
|
|
const installDev = true;
|
|
changes.push(...(await poetry_add_1.poetryAdd(entity, options, [upgrade], installDev)));
|
|
}
|
|
}
|
|
if (!changes.length) {
|
|
throw new no_fixes_applied_1.NoFixesCouldBeAppliedError();
|
|
}
|
|
if (!changes.some((c) => attempted_changes_summary_1.isSuccessfulChange(c))) {
|
|
handlerResult.failed.push({
|
|
original: entity,
|
|
changes,
|
|
});
|
|
}
|
|
else {
|
|
handlerResult.succeeded.push({
|
|
original: entity,
|
|
changes,
|
|
});
|
|
}
|
|
}
|
|
catch (error) {
|
|
debug(`Failed to fix ${entity.scanResult.identity.targetFile}.\nERROR: ${error}`);
|
|
handlerResult.failed.push({
|
|
original: entity,
|
|
tip: error.tip,
|
|
error,
|
|
});
|
|
}
|
|
return handlerResult;
|
|
}
|
|
//# sourceMappingURL=index.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 24881:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.poetryAdd = void 0;
|
|
const pathLib = __webpack_require__(85622);
|
|
const debugLib = __webpack_require__(15158);
|
|
const poetryFix = __webpack_require__(69671);
|
|
const validate_required_data_1 = __webpack_require__(57894);
|
|
const attempted_changes_summary_1 = __webpack_require__(70145);
|
|
const command_failed_to_run_error_1 = __webpack_require__(72353);
|
|
const no_fixes_applied_1 = __webpack_require__(80799);
|
|
const debug = debugLib('snyk-fix:python:poetryAdd');
|
|
async function poetryAdd(entity, options, upgrades, dev) {
|
|
var _a;
|
|
const changes = [];
|
|
let poetryCommand;
|
|
const { remediation, targetFile } = validate_required_data_1.validateRequiredData(entity);
|
|
try {
|
|
const targetFilePath = pathLib.resolve(entity.workspace.path, targetFile);
|
|
const { dir } = pathLib.parse(targetFilePath);
|
|
if (!options.dryRun && upgrades.length) {
|
|
const { stderr, stdout, command, exitCode } = await poetryFix.poetryAdd(dir, upgrades, {
|
|
dev,
|
|
python: (_a = entity.options.command) !== null && _a !== void 0 ? _a : undefined,
|
|
});
|
|
debug('`poetry add` returned:', { stderr, stdout, command });
|
|
if (exitCode !== 0) {
|
|
poetryCommand = command;
|
|
throwPoetryError(stderr, stdout, command);
|
|
}
|
|
}
|
|
changes.push(...attempted_changes_summary_1.generateSuccessfulChanges(upgrades, remediation.pin));
|
|
}
|
|
catch (error) {
|
|
changes.push(...attempted_changes_summary_1.generateFailedChanges(upgrades, remediation.pin, error, poetryCommand));
|
|
}
|
|
return changes;
|
|
}
|
|
exports.poetryAdd = poetryAdd;
|
|
function throwPoetryError(stderr, stdout, command) {
|
|
const ALREADY_UP_TO_DATE = 'No dependencies to install or update';
|
|
const INCOMPATIBLE_PYTHON = new RegExp(/Python requirement (.*) is not compatible/g, 'gm');
|
|
const SOLVER_PROBLEM = /SolverProblemError(.* version solving failed)/gms;
|
|
const incompatiblePythonError = INCOMPATIBLE_PYTHON.exec(stderr) || SOLVER_PROBLEM.exec(stdout);
|
|
if (incompatiblePythonError) {
|
|
throw new command_failed_to_run_error_1.CommandFailedError(`The current project's Python requirement ${incompatiblePythonError[1]} is not compatible with some of the required packages`, command);
|
|
}
|
|
const solverProblemError = SOLVER_PROBLEM.exec(stderr) || SOLVER_PROBLEM.exec(stdout);
|
|
if (solverProblemError) {
|
|
throw new command_failed_to_run_error_1.CommandFailedError(solverProblemError[0].trim(), command);
|
|
}
|
|
if (stderr.includes(ALREADY_UP_TO_DATE) ||
|
|
stdout.includes(ALREADY_UP_TO_DATE)) {
|
|
throw new command_failed_to_run_error_1.CommandFailedError('No dependencies could be updated as they seem to be at the correct versions. Make sure installed dependencies in the environment match those in the lockfile by running `poetry update`', command);
|
|
}
|
|
throw new no_fixes_applied_1.NoFixesCouldBeAppliedError();
|
|
}
|
|
//# sourceMappingURL=poetry-add.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 57894:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.validateRequiredData = void 0;
|
|
const missing_remediation_data_1 = __webpack_require__(95084);
|
|
const missing_file_name_1 = __webpack_require__(86920);
|
|
const no_fixes_applied_1 = __webpack_require__(80799);
|
|
function validateRequiredData(entity) {
|
|
const { remediation } = entity.testResult;
|
|
if (!remediation) {
|
|
throw new missing_remediation_data_1.MissingRemediationDataError();
|
|
}
|
|
const { targetFile } = entity.scanResult.identity;
|
|
if (!targetFile) {
|
|
throw new missing_file_name_1.MissingFileNameError();
|
|
}
|
|
const { workspace } = entity;
|
|
if (!workspace) {
|
|
throw new no_fixes_applied_1.NoFixesCouldBeAppliedError();
|
|
}
|
|
return { targetFile, remediation, workspace };
|
|
}
|
|
exports.validateRequiredData = validateRequiredData;
|
|
//# sourceMappingURL=validate-required-data.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 97090:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.pythonFix = void 0;
|
|
const debugLib = __webpack_require__(15158);
|
|
const pMap = __webpack_require__(54270);
|
|
const ora = __webpack_require__(63395);
|
|
const chalk = __webpack_require__(98250);
|
|
const load_handler_1 = __webpack_require__(7073);
|
|
const map_entities_per_handler_type_1 = __webpack_require__(78646);
|
|
const is_supported_1 = __webpack_require__(60174);
|
|
const debug = debugLib('snyk-fix:python');
|
|
async function pythonFix(entities, options) {
|
|
const spinner = ora({ isSilent: options.quiet, stream: process.stdout });
|
|
const spinnerMessage = 'Looking for supported Python items';
|
|
spinner.text = spinnerMessage;
|
|
spinner.start();
|
|
const handlerResult = {
|
|
python: {
|
|
succeeded: [],
|
|
failed: [],
|
|
skipped: [],
|
|
},
|
|
};
|
|
const results = handlerResult.python;
|
|
const { entitiesPerType, skipped: notSupported } = map_entities_per_handler_type_1.mapEntitiesPerHandlerType(entities);
|
|
results.skipped.push(...notSupported);
|
|
spinner.stopAndPersist({
|
|
text: spinnerMessage,
|
|
symbol: chalk.green('\n✔'),
|
|
});
|
|
await pMap(Object.keys(entitiesPerType), async (projectType) => {
|
|
const projectsToFix = entitiesPerType[projectType];
|
|
if (!projectsToFix.length) {
|
|
return;
|
|
}
|
|
const processingMessage = `Processing ${projectsToFix.length} ${projectType} items`;
|
|
const processedMessage = `Processed ${projectsToFix.length} ${projectType} items`;
|
|
spinner.text = processingMessage;
|
|
spinner.render();
|
|
try {
|
|
const handler = load_handler_1.loadHandler(projectType);
|
|
// drop unsupported Python entities early so only potentially fixable items get
|
|
// attempted to be fixed
|
|
const { fixable, skipped: notFixable } = await is_supported_1.partitionByFixable(projectsToFix);
|
|
results.skipped.push(...notFixable);
|
|
const { failed, skipped, succeeded } = await handler(fixable, options);
|
|
results.failed.push(...failed);
|
|
results.skipped.push(...skipped);
|
|
results.succeeded.push(...succeeded);
|
|
}
|
|
catch (e) {
|
|
debug(`Failed to fix ${projectsToFix.length} ${projectType} projects.\nError: ${e.message}`);
|
|
results.failed.push(...generateFailed(projectsToFix, e));
|
|
}
|
|
spinner.stopAndPersist({
|
|
text: processedMessage,
|
|
symbol: chalk.green('✔'),
|
|
});
|
|
}, {
|
|
concurrency: 5,
|
|
});
|
|
return handlerResult;
|
|
}
|
|
exports.pythonFix = pythonFix;
|
|
function generateFailed(projectsToFix, error) {
|
|
const failed = [];
|
|
for (const project of projectsToFix) {
|
|
failed.push({ original: project, error: error });
|
|
}
|
|
return failed;
|
|
}
|
|
//# sourceMappingURL=index.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 7073:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.loadHandler = void 0;
|
|
const pip_requirements_1 = __webpack_require__(81065);
|
|
const pipenv_pipfile_1 = __webpack_require__(28006);
|
|
const poetry_1 = __webpack_require__(60428);
|
|
const supported_handler_types_1 = __webpack_require__(56394);
|
|
function loadHandler(type) {
|
|
switch (type) {
|
|
case supported_handler_types_1.SUPPORTED_HANDLER_TYPES.REQUIREMENTS: {
|
|
return pip_requirements_1.pipRequirementsTxt;
|
|
}
|
|
case supported_handler_types_1.SUPPORTED_HANDLER_TYPES.PIPFILE: {
|
|
return pipenv_pipfile_1.pipenvPipfile;
|
|
}
|
|
case supported_handler_types_1.SUPPORTED_HANDLER_TYPES.POETRY: {
|
|
return poetry_1.poetry;
|
|
}
|
|
default: {
|
|
throw new Error('No handler available for requested project type');
|
|
}
|
|
}
|
|
}
|
|
exports.loadHandler = loadHandler;
|
|
//# sourceMappingURL=load-handler.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 78646:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.mapEntitiesPerHandlerType = void 0;
|
|
const debugLib = __webpack_require__(15158);
|
|
const get_handler_type_1 = __webpack_require__(10774);
|
|
const supported_handler_types_1 = __webpack_require__(56394);
|
|
const debug = debugLib('snyk-fix:python');
|
|
function mapEntitiesPerHandlerType(entities) {
|
|
const entitiesPerType = {
|
|
[supported_handler_types_1.SUPPORTED_HANDLER_TYPES.REQUIREMENTS]: [],
|
|
[supported_handler_types_1.SUPPORTED_HANDLER_TYPES.PIPFILE]: [],
|
|
[supported_handler_types_1.SUPPORTED_HANDLER_TYPES.POETRY]: [],
|
|
};
|
|
const skipped = [];
|
|
for (const entity of entities) {
|
|
const type = get_handler_type_1.getHandlerType(entity);
|
|
if (type) {
|
|
entitiesPerType[type].push(entity);
|
|
continue;
|
|
}
|
|
const userMessage = `${entity.scanResult.identity.targetFile} is not supported`;
|
|
debug(userMessage);
|
|
skipped.push({ original: entity, userMessage });
|
|
}
|
|
return { entitiesPerType, skipped };
|
|
}
|
|
exports.mapEntitiesPerHandlerType = mapEntitiesPerHandlerType;
|
|
//# sourceMappingURL=map-entities-per-handler-type.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 78078:
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.standardizePackageName = void 0;
|
|
/*
|
|
* https://www.python.org/dev/peps/pep-0426/#name
|
|
* All comparisons of distribution names MUST be case insensitive,
|
|
* and MUST consider hyphens and underscores to be equivalent.
|
|
*
|
|
*/
|
|
function standardizePackageName(name) {
|
|
return name.replace('_', '-').toLowerCase();
|
|
}
|
|
exports.standardizePackageName = standardizePackageName;
|
|
//# sourceMappingURL=standardize-package-name.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 56394:
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.SUPPORTED_HANDLER_TYPES = void 0;
|
|
var SUPPORTED_HANDLER_TYPES;
|
|
(function (SUPPORTED_HANDLER_TYPES) {
|
|
// shortname = display name
|
|
SUPPORTED_HANDLER_TYPES["REQUIREMENTS"] = "requirements.txt";
|
|
SUPPORTED_HANDLER_TYPES["PIPFILE"] = "Pipfile";
|
|
SUPPORTED_HANDLER_TYPES["POETRY"] = "pyproject.toml";
|
|
})(SUPPORTED_HANDLER_TYPES = exports.SUPPORTED_HANDLER_TYPES || (exports.SUPPORTED_HANDLER_TYPES = {}));
|
|
//# sourceMappingURL=supported-handler-types.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 71538:
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.isWithError = void 0;
|
|
function isWithError(r) {
|
|
return 'error' in r;
|
|
}
|
|
exports.isWithError = isWithError;
|
|
//# sourceMappingURL=types.js.map
|
|
|
|
/***/ })
|
|
|
|
};
|
|
;
|
|
//# sourceMappingURL=741.index.js.map
|