UNPKG

snyk

Version:

snyk library and cli utility

1,283 lines (1,189 loc) • 279 kB
exports.id = 784; exports.ids = [784]; exports.modules = { /***/ 61452: /***/ ((module) => { function webpackEmptyContext(req) { var e = new Error("Cannot find module '" + req + "'"); e.code = 'MODULE_NOT_FOUND'; throw e; } webpackEmptyContext.keys = () => ([]); webpackEmptyContext.resolve = webpackEmptyContext; webpackEmptyContext.id = 61452; module.exports = webpackEmptyContext; /***/ }), /***/ 3196: /***/ ((module) => { function webpackEmptyContext(req) { var e = new Error("Cannot find module '" + req + "'"); e.code = 'MODULE_NOT_FOUND'; throw e; } webpackEmptyContext.keys = () => ([]); webpackEmptyContext.resolve = webpackEmptyContext; webpackEmptyContext.id = 3196; module.exports = webpackEmptyContext; /***/ }), /***/ 3708: /***/ ((__unused_webpack_module, exports, __webpack_require__) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.validateTags = exports.generateTags = exports.generateProjectAttributes = exports.validateProjectAttributes = void 0; const chalk_1 = __webpack_require__(32589); const fs = __webpack_require__(35747); const Debug = __webpack_require__(15158); const pathUtil = __webpack_require__(85622); const cli_interface_1 = __webpack_require__(65266); const options_validator_1 = __webpack_require__(1570); const types_1 = __webpack_require__(94055); const config_1 = __webpack_require__(22541); const detect = __webpack_require__(45318); const spinner_1 = __webpack_require__(86766); const analytics = __webpack_require__(82744); const api_token_1 = __webpack_require__(95181); const print_deps_1 = __webpack_require__(79792); const monitor_1 = __webpack_require__(3959); const process_json_monitor_1 = __webpack_require__(21506); const snyk = __webpack_require__(9146); // TODO(kyegupov): fix import const formatters_1 = __webpack_require__(81329); const get_deps_from_plugin_1 = __webpack_require__(4842); const get_extra_project_count_1 = __webpack_require__(34355); const extract_package_manager_1 = __webpack_require__(22805); const convert_multi_plugin_res_to_multi_custom_1 = __webpack_require__(23110); const convert_single_splugin_res_to_multi_custom_1 = __webpack_require__(99695); const dev_count_analysis_1 = __webpack_require__(73898); const errors_1 = __webpack_require__(55191); const is_multi_project_scan_1 = __webpack_require__(62435); const ecosystems_1 = __webpack_require__(5168); const monitor_2 = __webpack_require__(62406); const process_command_args_1 = __webpack_require__(52369); const SEPARATOR = '\n-------------------------------------------------------\n'; const debug = Debug('snyk'); // This is used instead of `let x; try { x = await ... } catch { cleanup }` to avoid // declaring the type of x as possibly undefined. async function promiseOrCleanup(p, cleanup) { return p.catch((error) => { cleanup(); throw error; }); } // Returns an array of Registry responses (one per every sub-project scanned), a single response, // or an error message. async function monitor(...args0) { var _a; const { options, paths } = process_command_args_1.processCommandArgs(...args0); const results = []; if (options.id) { snyk.id = options.id; } if (options.allSubProjects && options['project-name']) { throw new Error('`--all-sub-projects` is currently not compatible with `--project-name`'); } if (options.docker && options['remote-repo-url']) { throw new Error('`--remote-repo-url` is not supported for container scans'); } // Handles no image arg provided to the container command until // a validation interface is implemented in the docker plugin. if (options.docker && paths.length === 0) { throw new errors_1.MissingArgError(); } api_token_1.apiOrOAuthTokenExists(); let contributors = []; if (!options.docker && analytics.allowAnalytics()) { try { contributors = await dev_count_analysis_1.getContributors(); } catch (err) { debug('error getting repo contributors', err); } } const ecosystem = ecosystems_1.getEcosystem(options); if (ecosystem) { const commandResult = await ecosystems_1.monitorEcosystem(ecosystem, paths, options); const [monitorResults, monitorErrors] = commandResult; return await monitor_2.getFormattedMonitorOutput(results, monitorResults, monitorErrors, options); } // Part 1: every argument is a scan target; process them sequentially for (const path of paths) { debug(`Processing ${path}...`); try { validateMonitorPath(path, options.docker); let analysisType = 'all'; let packageManager; if (is_multi_project_scan_1.isMultiProjectScan(options)) { analysisType = 'all'; } else if (options.docker) { analysisType = 'docker'; } else { packageManager = detect.detectPackageManager(path, options); } await options_validator_1.validateOptions(options, packageManager); const targetFile = !options.scanAllUnmanaged && options.docker && !options.file // snyk monitor --docker (without --file) ? undefined : options.file || detect.detectPackageFile(path); const displayPath = pathUtil.relative('.', pathUtil.join(path, targetFile || '')); const analyzingDepsSpinnerLabel = 'Analyzing ' + (packageManager ? packageManager : analysisType) + ' dependencies for ' + displayPath; await spinner_1.spinner(analyzingDepsSpinnerLabel); // Scan the project dependencies via a plugin debug('getDepsFromPlugin ...'); // each plugin will be asked to scan once per path // some return single InspectResult & newer ones return Multi const inspectResult = await promiseOrCleanup(get_deps_from_plugin_1.getDepsFromPlugin(path, { ...options, path, packageManager, }), spinner_1.spinner.clear(analyzingDepsSpinnerLabel)); analytics.add('pluginName', inspectResult.plugin.name); // We send results from "all-sub-projects" scanning as different Monitor objects // multi result will become default, so start migrating code to always work with it let perProjectResult; if (!cli_interface_1.legacyPlugin.isMultiResult(inspectResult)) { perProjectResult = convert_single_splugin_res_to_multi_custom_1.convertSingleResultToMultiCustom(inspectResult); } else { perProjectResult = convert_multi_plugin_res_to_multi_custom_1.convertMultiResultToMultiCustom(inspectResult); } const failedResults = inspectResult .failedResults; if (failedResults === null || failedResults === void 0 ? void 0 : failedResults.length) { failedResults.forEach((result) => { results.push({ ok: false, data: new errors_1.MonitorError(500, result.errMessage), path: result.targetFile || '', }); }); } const postingMonitorSpinnerLabel = 'Posting monitor snapshot for ' + displayPath + ' ...'; await spinner_1.spinner(postingMonitorSpinnerLabel); // Post the project dependencies to the Registry for (const projectDeps of perProjectResult.scannedProjects) { try { if (!projectDeps.depGraph && !projectDeps.depTree) { debug('scannedProject is missing depGraph or depTree, cannot run test/monitor'); throw new errors_1.FailedToRunTestError('Your monitor request could not be completed. Please email support@snyk.io'); } const extractedPackageManager = extract_package_manager_1.extractPackageManager(projectDeps, perProjectResult, options); analytics.add('packageManager', extractedPackageManager); const projectName = getProjectName(projectDeps); if (projectDeps.depGraph) { debug(`Processing ${(_a = projectDeps.depGraph.rootPkg) === null || _a === void 0 ? void 0 : _a.name}...`); print_deps_1.maybePrintDepGraph(options, projectDeps.depGraph); } if (projectDeps.depTree) { debug(`Processing ${projectDeps.depTree.name}...`); print_deps_1.maybePrintDepTree(options, projectDeps.depTree); } const tFile = projectDeps.targetFile || targetFile; const targetFileRelativePath = projectDeps.plugin.targetFile || (tFile && pathUtil.join(pathUtil.resolve(path), tFile)) || ''; const res = await promiseOrCleanup(monitor_1.monitor(path, generateMonitorMeta(options, extractedPackageManager), projectDeps, options, projectDeps.plugin, targetFileRelativePath, contributors, generateProjectAttributes(options), generateTags(options)), spinner_1.spinner.clear(postingMonitorSpinnerLabel)); res.path = path; const monOutput = formatters_1.formatMonitorOutput(extractedPackageManager, res, options, projectName, await get_extra_project_count_1.getExtraProjectCount(path, options, inspectResult)); // push a good result results.push({ ok: true, data: monOutput, path, projectName }); } catch (err) { // pushing this error allow this inner loop to keep scanning the projects // even if 1 in 100 fails results.push({ ok: false, data: err, path }); } } } catch (err) { // push this error, the loop continues results.push({ ok: false, data: err, path }); } finally { spinner_1.spinner.clearAll(); } } // Part 2: process the output from the Registry if (options.json) { return process_json_monitor_1.processJsonMonitorResponse(results); } const output = results .map((res) => { if (res.ok) { return res.data; } const errorMessage = res.data && res.data.userMessage ? chalk_1.default.bold.red(res.data.userMessage) : res.data ? res.data.message : 'Unknown error occurred.'; return (chalk_1.default.bold.white('\nMonitoring ' + res.path + '...\n\n') + errorMessage); }) .join('\n' + SEPARATOR); if (results.every((res) => res.ok)) { return output; } throw new Error(output); } exports.default = monitor; function generateMonitorMeta(options, packageManager) { return { method: 'cli', packageManager, 'policy-path': options['policy-path'], 'project-name': options['project-name'] || config_1.default.PROJECT_NAME, isDocker: !!options.docker, prune: !!options.pruneRepeatedSubdependencies, 'remote-repo-url': options['remote-repo-url'], targetReference: options['target-reference'], }; } /** * Parse an attribute from the CLI into the relevant enum type. * * @param attribute The project attribute (e.g. environment) * @param permitted Permitted options * @param options CLI options provided * @returns An array of attributes to set on the project or undefined to mean "do not touch". */ function getProjectAttribute(attribute, permitted, options) { const permittedValues = Object.values(permitted); if (options[attribute] === undefined) { return undefined; } // Explicit flag to clear the existing values for this attribute already set on the project // e.g. if you specify --environment= // then this means you want to remove existing environment values on the project. if (options[attribute] === '') { return []; } // When it's specified without the =, we raise an explicit error to avoid // accidentally clearing the existing values. if (options[attribute] === true) { throw new errors_1.ValidationError(`--${attribute} must contain an '=' with a comma-separated list of values. To clear all existing values, pass no values i.e. --${attribute}=`); } const values = options[attribute].split(','); const extra = values.filter((value) => !permittedValues.includes(value)); if (extra.length > 0) { throw new errors_1.ValidationError(`${extra.length} invalid ${attribute}: ${extra.join(', ')}. ` + `Possible values are: ${permittedValues.join(', ')}`); } return values; } function validateProjectAttributes(options) { // The validation is deep within the parsing, so call the generate but throw away the return for simplicity. // Using this method makes it much clearer what the intent is of the caller. generateProjectAttributes(options); } exports.validateProjectAttributes = validateProjectAttributes; function generateProjectAttributes(options) { return { criticality: getProjectAttribute('project-business-criticality', types_1.PROJECT_CRITICALITY, options), environment: getProjectAttribute('project-environment', types_1.PROJECT_ENVIRONMENT, options), lifecycle: getProjectAttribute('project-lifecycle', types_1.PROJECT_LIFECYCLE, options), }; } exports.generateProjectAttributes = generateProjectAttributes; /** * Parse CLI --tags options into an internal data structure. * * If this returns undefined, it means "do not touch the existing tags on the project". * * Anything else means "replace existing tags on the project with this list" even if empty. * * @param options CLI options * @returns List of parsed tags or undefined if they are to be left untouched. */ function generateTags(options) { if (options['project-tags'] === undefined && options['tags'] === undefined) { return undefined; } if (options['project-tags'] !== undefined && options['tags'] !== undefined) { throw new errors_1.ValidationError('Only one of --tags or --project-tags may be specified, not both'); } const rawTags = options['tags'] === undefined ? options['project-tags'] : options['tags']; if (rawTags === '') { return []; } // When it's specified without the =, we raise an explicit error to avoid // accidentally clearing the existing tags; if (rawTags === true) { throw new errors_1.ValidationError(`--project-tags must contain an '=' with a comma-separated list of pairs (also separated with an '='). To clear all existing values, pass no values i.e. --project-tags=`); } const keyEqualsValuePairs = rawTags.split(','); const tags = []; for (const keyEqualsValue of keyEqualsValuePairs) { const parts = keyEqualsValue.split('='); if (parts.length !== 2) { throw new errors_1.ValidationError(`The tag "${keyEqualsValue}" does not have an "=" separating the key and value. For example: --project-tag=KEY=VALUE`); } tags.push({ key: parts[0], value: parts[1], }); } return tags; } exports.generateTags = generateTags; function validateTags(options) { // The validation is deep within the parsing, so call the generate but throw away the return for simplicity. // Using this method makes it much clearer what the intent is of the caller. generateTags(options); } exports.validateTags = validateTags; function validateMonitorPath(path, isDocker) { const exists = fs.existsSync(path); if (!exists && !isDocker) { throw new Error('"' + path + '" is not a valid path for "snyk monitor"'); } } function getProjectName(projectDeps) { var _a, _b, _c, _d; return (((_a = projectDeps.meta) === null || _a === void 0 ? void 0 : _a.gradleProjectName) || ((_c = (_b = projectDeps.depGraph) === null || _b === void 0 ? void 0 : _b.rootPkg) === null || _c === void 0 ? void 0 : _c.name) || ((_d = projectDeps.depTree) === null || _d === void 0 ? void 0 : _d.name)); } /***/ }), /***/ 21506: /***/ ((__unused_webpack_module, exports) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.processJsonMonitorResponse = void 0; function processJsonMonitorResponse(results) { let dataToSend = results.map((result) => { if (result.ok) { const jsonData = JSON.parse(result.data); if (result.projectName) { jsonData.projectName = result.projectName; } return jsonData; } return { ok: false, error: result.data.message, path: result.path }; }); // backwards compat - strip array if only one result dataToSend = dataToSend.length === 1 ? dataToSend[0] : dataToSend; const stringifiedData = JSON.stringify(dataToSend, null, 2); if (results.every((res) => res.ok)) { return stringifiedData; } const err = new Error(stringifiedData); err.json = stringifiedData; throw err; } exports.processJsonMonitorResponse = processJsonMonitorResponse; /***/ }), /***/ 52369: /***/ ((__unused_webpack_module, exports) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.processCommandArgs = void 0; function processCommandArgs(...args) { let options = {}; if (typeof args[args.length - 1] === 'object') { options = args.pop(); } args = args.filter(Boolean); // For repository scanning, populate with default path (cwd) if no path given if (args.length === 0 && !options.docker) { args.unshift(process.cwd()); } return { options, paths: args }; } exports.processCommandArgs = processCommandArgs; /***/ }), /***/ 55246: /***/ ((__unused_webpack_module, exports) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.TestCommandResult = exports.CommandResult = void 0; class CommandResult { constructor(result) { this.result = result; } toString() { return this.result; } getDisplayResults() { return this.result; } } exports.CommandResult = CommandResult; class TestCommandResult extends CommandResult { constructor() { super(...arguments); this.jsonResult = ''; this.sarifResult = ''; } getJsonResult() { return this.jsonResult; } getSarifResult() { return this.sarifResult; } static createHumanReadableTestCommandResult(humanReadableResult, jsonResult, sarifResult) { return new HumanReadableTestCommandResult(humanReadableResult, jsonResult, sarifResult); } static createJsonTestCommandResult(stdout, jsonResult, sarifResult) { return new JsonTestCommandResult(stdout, jsonResult, sarifResult); } } exports.TestCommandResult = TestCommandResult; class HumanReadableTestCommandResult extends TestCommandResult { constructor(humanReadableResult, jsonResult, sarifResult) { super(humanReadableResult); this.jsonResult = ''; this.sarifResult = ''; this.jsonResult = jsonResult; if (sarifResult) { this.sarifResult = sarifResult; } } getJsonResult() { return this.jsonResult; } getSarifResult() { return this.sarifResult; } } class JsonTestCommandResult extends TestCommandResult { constructor(stdout, jsonResult, sarifResult) { super(stdout); if (jsonResult) { this.jsonResult = jsonResult; } if (sarifResult) { this.sarifResult = sarifResult; } else { this.jsonResult = stdout; } } getJsonResult() { return this.jsonResult; } getSarifResult() { return this.sarifResult; } } /***/ }), /***/ 65623: /***/ ((__unused_webpack_module, exports) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.CALL_PATH_TRAILING_ELEMENTS = exports.CALL_PATH_LEADING_ELEMENTS = exports.PATH_HIDDEN_ELEMENTS = exports.PATH_SEPARATOR = void 0; // Separator used while displaying various paths (e.g. package paths, call // paths) to the user exports.PATH_SEPARATOR = ' > '; // String used to signify hidden path elements e.g. for abbreviated paths exports.PATH_HIDDEN_ELEMENTS = '...'; // Number of function names to show in the beginning of an abbreviated call path exports.CALL_PATH_LEADING_ELEMENTS = 2; // Number of function names to show in the end of an abbreviated call path exports.CALL_PATH_TRAILING_ELEMENTS = 2; /***/ }), /***/ 69813: /***/ ((__unused_webpack_module, exports) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.isUnmanagedEcosystem = void 0; function isUnmanagedEcosystem(ecosystem) { return ecosystem === 'cpp'; } exports.isUnmanagedEcosystem = isUnmanagedEcosystem; /***/ }), /***/ 5168: /***/ ((__unused_webpack_module, exports, __webpack_require__) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getEcosystem = exports.getEcosystemForTest = void 0; var test_1 = __webpack_require__(60937); Object.defineProperty(exports, "testEcosystem", ({ enumerable: true, get: function () { return test_1.testEcosystem; } })); var monitor_1 = __webpack_require__(62406); Object.defineProperty(exports, "monitorEcosystem", ({ enumerable: true, get: function () { return monitor_1.monitorEcosystem; } })); var plugins_1 = __webpack_require__(78053); Object.defineProperty(exports, "getPlugin", ({ enumerable: true, get: function () { return plugins_1.getPlugin; } })); /** * Ecosystems are listed here if you opt in to the new plugin test flow. * This is a breaking change to the old plugin formats, so only a select few * plugins currently work with it. * * Currently container scanning is not yet ready to work with this flow, * hence this is in a separate function from getEcosystem(). */ function getEcosystemForTest(options) { if (options.unmanaged) { return 'cpp'; } if (options.code) { return 'code'; } return null; } exports.getEcosystemForTest = getEcosystemForTest; function getEcosystem(options) { if (options.unmanaged) { return 'cpp'; } if (options.docker) { return 'docker'; } return null; } exports.getEcosystem = getEcosystem; /***/ }), /***/ 62406: /***/ ((__unused_webpack_module, exports, __webpack_require__) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getFormattedMonitorOutput = exports.generateMonitorDependenciesRequest = exports.monitorEcosystem = void 0; const chalk_1 = __webpack_require__(32589); const config_1 = __webpack_require__(22541); const is_ci_1 = __webpack_require__(10090); const promise_1 = __webpack_require__(90430); const spinner_1 = __webpack_require__(86766); const plugins_1 = __webpack_require__(78053); const formatters_1 = __webpack_require__(81329); const get_extra_project_count_1 = __webpack_require__(34355); const errors_1 = __webpack_require__(55191); const policy_1 = __webpack_require__(4669); const api_token_1 = __webpack_require__(95181); const resolve_monitor_facts_1 = __webpack_require__(47630); const monitor_1 = __webpack_require__(3708); const common_1 = __webpack_require__(69813); const policy_2 = __webpack_require__(32615); const SEPARATOR = '\n-------------------------------------------------------\n'; async function monitorEcosystem(ecosystem, paths, options) { const plugin = plugins_1.getPlugin(ecosystem); monitor_1.validateTags(options); monitor_1.validateProjectAttributes(options); const scanResultsByPath = {}; for (const path of paths) { try { await spinner_1.spinner(`Analyzing dependencies in ${path}`); options.path = path; const pluginResponse = await plugin.scan(options); scanResultsByPath[path] = pluginResponse.scanResults; const policy = await policy_2.findAndLoadPolicy(path, 'cpp', options); if (policy) { scanResultsByPath[path].forEach((scanResult) => (scanResult.policy = policy.toString())); } } catch (error) { if (ecosystem === 'docker' && error.statusCode === 401 && error.message === 'authentication required') { throw new errors_1.DockerImageNotFoundError(path); } if (ecosystem === 'docker' && error.message === 'invalid image format') { throw new errors_1.DockerImageNotFoundError(path); } throw error; } finally { spinner_1.spinner.clearAll(); } } const [monitorResults, errors] = await selectAndExecuteMonitorStrategy(ecosystem, scanResultsByPath, options); return [monitorResults, errors]; } exports.monitorEcosystem = monitorEcosystem; async function selectAndExecuteMonitorStrategy(ecosystem, scanResultsByPath, options) { return common_1.isUnmanagedEcosystem(ecosystem) ? await resolve_monitor_facts_1.resolveAndMonitorFacts(scanResultsByPath, options) : await monitorDependencies(scanResultsByPath, options); } async function generateMonitorDependenciesRequest(scanResult, options) { // WARNING! This mutates the payload. The project name logic should be handled in the plugin. scanResult.name = options['project-name'] || config_1.default.PROJECT_NAME || scanResult.name; // WARNING! This mutates the payload. Policy logic should be in the plugin. const policy = await policy_1.findAndLoadPolicyForScanResult(scanResult, options); if (policy !== undefined) { scanResult.policy = policy.toString(); } return { scanResult, method: 'cli', projectName: options['project-name'] || config_1.default.PROJECT_NAME || undefined, tags: monitor_1.generateTags(options), attributes: monitor_1.generateProjectAttributes(options), }; } exports.generateMonitorDependenciesRequest = generateMonitorDependenciesRequest; async function monitorDependencies(scans, options) { const results = []; const errors = []; for (const [path, scanResults] of Object.entries(scans)) { await spinner_1.spinner(`Monitoring dependencies in ${path}`); for (const scanResult of scanResults) { const monitorDependenciesRequest = await generateMonitorDependenciesRequest(scanResult, options); const configOrg = config_1.default.org ? decodeURIComponent(config_1.default.org) : undefined; const payload = { method: 'PUT', url: `${config_1.default.API}/monitor-dependencies`, json: true, headers: { 'x-is-ci': is_ci_1.isCI(), authorization: api_token_1.getAuthHeader(), }, body: monitorDependenciesRequest, qs: { org: options.org || configOrg, }, }; try { const response = await promise_1.makeRequest(payload); results.push({ ...response, path, scanResult, }); } catch (error) { if (error.code === 401) { throw errors_1.AuthFailedError(); } if (error.code >= 400 && error.code < 500) { throw new errors_1.MonitorError(error.code, error.message); } errors.push({ error: 'Could not monitor dependencies in ' + path, path, scanResult, }); } } spinner_1.spinner.clearAll(); } return [results, errors]; } async function getFormattedMonitorOutput(results, monitorResults, errors, options) { for (const monitorResult of monitorResults) { let monOutput = ''; if (monitorResult.ok) { monOutput = formatters_1.formatMonitorOutput(monitorResult.scanResult.identity.type, monitorResult, options, monitorResult.projectName, await get_extra_project_count_1.getExtraProjectCount(monitorResult.path, options, // TODO: Fix to pass the old "inspectResult.plugin.meta.allSubProjectNames", which ecosystem uses this? // "allSubProjectNames" can become a Fact returned by a plugin. {})); } else { monOutput = formatters_1.formatErrorMonitorOutput(monitorResult.scanResult.identity.type, monitorResult, options); } results.push({ ok: true, data: monOutput, path: monitorResult.path, projectName: monitorResult.id, }); } for (const monitorError of errors) { results.push({ ok: false, data: new errors_1.MonitorError(500, monitorError.error), path: monitorError.path, }); } const outputString = results .map((res) => { if (res.ok) { return res.data; } const errorMessage = res.data && res.data.userMessage ? chalk_1.default.bold.red(res.data.userMessage) : res.data ? res.data.message : 'Unknown error occurred.'; return (chalk_1.default.bold.white('\nMonitoring ' + res.path + '...\n\n') + errorMessage); }) .join('\n' + SEPARATOR); if (results.every((res) => res.ok)) { return outputString; } throw new Error(outputString); } exports.getFormattedMonitorOutput = getFormattedMonitorOutput; /***/ }), /***/ 33077: /***/ ((__unused_webpack_module, exports, __webpack_require__) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.extractAndApplyPluginAnalytics = void 0; const analytics = __webpack_require__(82744); function extractAndApplyPluginAnalytics(pluginAnalytics, asyncRequestToken) { if (asyncRequestToken) { analytics.add('asyncRequestToken', asyncRequestToken); } for (const { name, data } of pluginAnalytics) { analytics.add(name, data); } } exports.extractAndApplyPluginAnalytics = extractAndApplyPluginAnalytics; /***/ }), /***/ 78053: /***/ ((__unused_webpack_module, exports, __webpack_require__) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getPlugin = void 0; const cppPlugin = __webpack_require__(96957); const dockerPlugin = __webpack_require__(61165); const sast_1 = __webpack_require__(93221); const EcosystemPlugins = { cpp: cppPlugin, // TODO: not any docker: dockerPlugin, code: sast_1.codePlugin, }; function getPlugin(ecosystem) { return EcosystemPlugins[ecosystem]; } exports.getPlugin = getPlugin; /***/ }), /***/ 4669: /***/ ((__unused_webpack_module, exports, __webpack_require__) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.filterIgnoredIssues = exports.findAndLoadPolicyForScanResult = void 0; const path = __webpack_require__(85622); const policy_1 = __webpack_require__(32615); async function findAndLoadPolicyForScanResult(scanResult, options) { const targetFileRelativePath = scanResult.identity.targetFile ? path.join(path.resolve(`${options.path}`), scanResult.identity.targetFile) : undefined; const targetFileDir = targetFileRelativePath ? path.parse(targetFileRelativePath).dir : undefined; const scanType = options.docker ? 'docker' : scanResult.identity.type; // TODO: fix this and send only send when we used resolve-deps for node // it should be a ExpandedPkgTree type instead const packageExpanded = undefined; const policy = (await policy_1.findAndLoadPolicy(options.path, scanType, options, packageExpanded, targetFileDir)); // TODO: findAndLoadPolicy() does not return a string! return policy; } exports.findAndLoadPolicyForScanResult = findAndLoadPolicyForScanResult; function filterIgnoredIssues(issues, issuesData, policy) { if (!(policy === null || policy === void 0 ? void 0 : policy.ignore)) { return [issues, issuesData]; } const filteredIssuesData = { ...issuesData }; const filteredIssues = issues.filter((issue) => { const ignoredIssue = policy.ignore[issue.issueId]; if (!ignoredIssue) { return true; } const allResourcesRule = ignoredIssue.find((element) => '*' in element); if (!allResourcesRule) { return true; } const expiredIgnoreRule = new Date(allResourcesRule['*'].expires) < new Date(); if (!expiredIgnoreRule) { delete filteredIssuesData[issue.issueId]; return false; } return true; }); return [filteredIssues, filteredIssuesData]; } exports.filterIgnoredIssues = filterIgnoredIssues; /***/ }), /***/ 47630: /***/ ((__unused_webpack_module, exports, __webpack_require__) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.resolveAndMonitorFacts = void 0; const spinner_1 = __webpack_require__(86766); const polling_monitor_1 = __webpack_require__(59354); const plugin_analytics_1 = __webpack_require__(33077); const errors_1 = __webpack_require__(55191); const common_1 = __webpack_require__(74434); async function resolveAndMonitorFacts(scans, options) { const results = []; const errors = []; for (const [path, scanResults] of Object.entries(scans)) { await spinner_1.spinner(`Resolving and Monitoring fileSignatures in ${path}`); for (const scanResult of scanResults) { try { const res = await polling_monitor_1.requestMonitorPollingToken(options, true, scanResult); if (scanResult.analytics) { plugin_analytics_1.extractAndApplyPluginAnalytics(scanResult.analytics, res.token); } const resolutionMeta = common_1.extractResolutionMetaFromScanResult(scanResult); const { maxAttempts, pollInterval } = res.pollingTask; const attemptsCount = 0; const response = await polling_monitor_1.pollingMonitorWithTokenUntilDone(res.token, true, options, pollInterval, attemptsCount, maxAttempts, resolutionMeta); const ecosystemMonitorResult = { ...response, path, scanResult, }; results.push(ecosystemMonitorResult); } catch (error) { if (error.code === 401) { throw errors_1.AuthFailedError(); } if (error.code >= 400 && error.code < 500) { throw new errors_1.MonitorError(error.code, error.message); } errors.push({ error: 'Could not monitor dependencies in ' + path, path, scanResult, }); } } spinner_1.spinner.clearAll(); } return [results, errors]; } exports.resolveAndMonitorFacts = resolveAndMonitorFacts; /***/ }), /***/ 85164: /***/ ((__unused_webpack_module, exports, __webpack_require__) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.resolveAndTestFacts = void 0; const spinner_1 = __webpack_require__(86766); const polling_test_1 = __webpack_require__(77584); const plugin_analytics_1 = __webpack_require__(33077); const policy_1 = __webpack_require__(32615); const policy_2 = __webpack_require__(4669); async function resolveAndTestFacts(ecosystem, scans, options) { const results = []; const errors = []; for (const [path, scanResults] of Object.entries(scans)) { await spinner_1.spinner(`Resolving and Testing fileSignatures in ${path}`); for (const scanResult of scanResults) { try { const res = await polling_test_1.requestTestPollingToken(options, true, scanResult); if (scanResult.analytics) { plugin_analytics_1.extractAndApplyPluginAnalytics(scanResult.analytics, res.token); } const { maxAttempts, pollInterval } = res.pollingTask; const attemptsCount = 0; const response = await polling_test_1.pollingTestWithTokenUntilDone(res.token, ecosystem, options, pollInterval, attemptsCount, maxAttempts); const policy = await policy_1.findAndLoadPolicy(path, 'cpp', options); const [issues, issuesData] = policy_2.filterIgnoredIssues(response.issues, response.issuesData, policy); results.push({ issues, issuesData, depGraphData: response === null || response === void 0 ? void 0 : response.depGraphData, depsFilePaths: response === null || response === void 0 ? void 0 : response.depsFilePaths, fileSignaturesDetails: response === null || response === void 0 ? void 0 : response.fileSignaturesDetails, }); } catch (error) { const hasStatusCodeError = error.code >= 400 && error.code <= 500; if (hasStatusCodeError) { errors.push(error.message); continue; } const failedPath = path ? `in ${path}` : '.'; errors.push(`Could not test dependencies ${failedPath}`); } } } spinner_1.spinner.clearAll(); return [results, errors]; } exports.resolveAndTestFacts = resolveAndTestFacts; /***/ }), /***/ 60937: /***/ ((__unused_webpack_module, exports, __webpack_require__) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.selectAndExecuteTestStrategy = exports.testEcosystem = void 0; const config_1 = __webpack_require__(22541); const is_ci_1 = __webpack_require__(10090); const promise_1 = __webpack_require__(90430); const types_1 = __webpack_require__(55246); const spinner_1 = __webpack_require__(86766); const plugins_1 = __webpack_require__(78053); const common_1 = __webpack_require__(53110); const api_token_1 = __webpack_require__(95181); const resolve_test_facts_1 = __webpack_require__(85164); const common_2 = __webpack_require__(69813); async function testEcosystem(ecosystem, paths, options) { const plugin = plugins_1.getPlugin(ecosystem); // TODO: this is an intermediate step before consolidating ecosystem plugins // to accept flows that act differently in the testDependencies step if (plugin.test) { const { readableResult: res, sarifResult: sarifRes } = await plugin.test(paths, options); return types_1.TestCommandResult.createHumanReadableTestCommandResult(res, '', sarifRes); } const scanResultsByPath = {}; for (const path of paths) { await spinner_1.spinner(`Scanning dependencies in ${path}`); options.path = path; const pluginResponse = await plugin.scan(options); scanResultsByPath[path] = pluginResponse.scanResults; } spinner_1.spinner.clearAll(); const [testResults, errors] = await selectAndExecuteTestStrategy(ecosystem, scanResultsByPath, options); const stringifiedData = JSON.stringify(testResults, null, 2); if (options.json) { return types_1.TestCommandResult.createJsonTestCommandResult(stringifiedData); } const emptyResults = []; const scanResults = emptyResults.concat(...Object.values(scanResultsByPath)); const readableResult = await plugin.display(scanResults, testResults, errors, options); return types_1.TestCommandResult.createHumanReadableTestCommandResult(readableResult, stringifiedData); } exports.testEcosystem = testEcosystem; async function selectAndExecuteTestStrategy(ecosystem, scanResultsByPath, options) { return common_2.isUnmanagedEcosystem(ecosystem) ? await resolve_test_facts_1.resolveAndTestFacts(ecosystem, scanResultsByPath, options) : await testDependencies(scanResultsByPath, options); } exports.selectAndExecuteTestStrategy = selectAndExecuteTestStrategy; async function testDependencies(scans, options) { const results = []; const errors = []; for (const [path, scanResults] of Object.entries(scans)) { await spinner_1.spinner(`Testing dependencies in ${path}`); for (const scanResult of scanResults) { const payload = { method: 'POST', url: `${config_1.default.API}/test-dependencies`, json: true, headers: { 'x-is-ci': is_ci_1.isCI(), authorization: api_token_1.getAuthHeader(), }, body: { scanResult, }, qs: common_1.assembleQueryString(options), }; try { const response = await promise_1.makeRequest(payload); results.push({ issues: response.result.issues, issuesData: response.result.issuesData, depGraphData: response.result.depGraphData, }); } catch (error) { if (error.code >= 400 && error.code < 500) { throw new Error(error.message); } errors.push('Could not test dependencies in ' + path); } } } spinner_1.spinner.clearAll(); return [results, errors]; } /***/ }), /***/ 59369: /***/ ((__unused_webpack_module, exports) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.abridgeErrorMessage = void 0; function abridgeErrorMessage(msg, maxLen, ellipsis = ' ... ') { if (msg.length <= maxLen) { return msg; } const toKeep = Math.floor((maxLen - ellipsis.length) / 2); return (msg.slice(0, toKeep) + ellipsis + msg.slice(msg.length - toKeep, msg.length)); } exports.abridgeErrorMessage = abridgeErrorMessage; /***/ }), /***/ 86033: /***/ ((__unused_webpack_module, exports, __webpack_require__) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.InvalidRemoteUrlError = void 0; const custom_error_1 = __webpack_require__(17188); class InvalidRemoteUrlError extends custom_error_1.CustomError { constructor() { super(InvalidRemoteUrlError.ERROR_MESSAGE); } } exports.InvalidRemoteUrlError = InvalidRemoteUrlError; InvalidRemoteUrlError.ERROR_MESSAGE = 'Invalid argument provided for --remote-repo-url. Value must be a string.'; /***/ }), /***/ 63011: /***/ ((__unused_webpack_module, exports, __webpack_require__) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.hasFeatureFlag = exports.isFeatureFlagSupportedForOrg = void 0; const request_1 = __webpack_require__(52050); const api_token_1 = __webpack_require__(95181); const config_1 = __webpack_require__(22541); const common_1 = __webpack_require__(53110); const errors_1 = __webpack_require__(55191); async function isFeatureFlagSupportedForOrg(featureFlag, org) { const response = await request_1.makeRequest({ method: 'GET', headers: { Authorization: api_token_1.getAuthHeader(), }, qs: common_1.assembleQueryString({ org }), url: `${config_1.default.API}/cli-config/feature-flags/${featureFlag}`, gzip: true, json: true, }); return response.body; } exports.isFeatureFlagSupportedForOrg = isFeatureFlagSupportedForOrg; async function hasFeatureFlag(featureFlag, options) { const { code, error, ok } = await isFeatureFlagSupportedForOrg(featureFlag, options.org); if (code === 401 || code === 403) { throw errors_1.AuthFailedError(error, code); } return ok; } exports.hasFeatureFlag = hasFeatureFlag; /***/ }), /***/ 46123: /***/ ((__unused_webpack_module, exports, __webpack_require__) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.find = exports.getStats = exports.readDirectory = void 0; const fs = __webpack_require__(35747); const pathLib = __webpack_require__(85622); const sortBy = __webpack_require__(58254); const groupBy = __webpack_require__(20276); const detect_1 = __webpack_require__(45318); const debugModule = __webpack_require__(15158); const debug = debugModule('snyk:find-files'); // TODO: use util.promisify once we move to node 8 /** * Returns files inside given file path. * * @param path file path. */ async function readDirectory(path) { return await new Promise((resolve, reject) => { fs.readdir(path, (err, files) => { if (err) { reject(err); } resolve(files); }); }); } exports.readDirectory = readDirectory; /** * Returns file stats object for given file path. * * @param path path to file or directory. */ async function getStats(path) { return await new Promise((resolve, reject) => { fs.stat(path, (err, stats) => { if (err) { reject(err); } resolve(stats); }); }); } exports.getStats = getStats; /** * Find all files in given search path. Returns paths to files found. * * @param path file path to search. * @param ignore (optional) files to ignore. Will always ignore node_modules. * @param filter (optional) file names to find. If not provided all files are returned. * @param levelsDeep (optional) how many levels deep to search, defaults to two, this path and one sub directory. */ async function find(path, ignore = [], filter = [], levelsDeep = 4) { const found = []; const foundAll = []; // ensure we ignore find against node_modules path. if (path.endsWith('node_modules')) { return { files: found, allFilesFound: foundAll }; } // ensure node_modules is always ignored if (!ignore.includes('node_modules')) { ignore.push('node_modules'); } try { if (levelsDeep < 0) { return { files: found, allFilesFound: foundAll }; } else { levelsDeep--; } const fileStats = await getStats(path); if (fileStats.isDirectory()) { const { files, allFilesFound } = await findInDirectory(path, ignore, filter, levelsDeep); found.push(...files); foundAll.push(...allFilesFound); } else if (fileStats.isFile()) { const fileFound = findFile(path, filter); if (fileFound) { found.push(fileFound); foundAll.push(fileFound); } } const filteredOutFiles = foundAll.filter((f) => !found.includes(f)); if (filteredOutFiles.length) { debug(`Filtered out ${filteredOutFiles.length}/${foundAll.length} files: ${filteredOutFiles.join(', ')}`); } return { files: filterForDefaultManifests(found), allFilesFound: foundAll }; } catch (err) { throw new Error(`Error finding files in path '${path}'.\n${err.message}`); } } exports.find = find; function findFile(path, filter = []) { if (filter.length > 0) { const filename = pathLib.basename(path); if (filter.includes(filename)) { return path; } } else { return path; } return null; } async function findInDirectory(path, ignore = [], filter = [], levelsDeep = 4) { const files = await readDirectory(path); const toFind = files .filter((file) => !ignore.includes(file)) .map((file) => { const resolvedPath = pathLib.resolve(path, file); if (!fs.existsSync(resolvedPath)) { debug('File does not seem to exist, skipping: ', file); return { files: [], allFilesFound: [] }; } return find(resolvedPath, ignore, filter, levelsDeep); }); const found = await Promise.all(toFind); return { files: Array.prototype.concat.apply([], found.map((f) => f.files)), allFilesFound: Array.prototype.concat.apply([], found.map((f) => f.allFilesFound)), }; } function filterForDefaultManifests(files) { // take all the files in the same dir & filter out // based on package Manager if (files.length <= 1) { return files; } const filteredFiles = []; const beforeSort = files .filter(Boolean) .filter((p) => fs.existsSync(p)) .map((p) => ({ path: p, ...pathLib.parse(p), packageManager: detectProjectTypeFromFile(p), })); const sorted = sortBy(beforeSort, 'dir'); const foundFiles = groupBy(sorted, 'dir'); for (const directory of Object.keys(foundFiles)) { const filesInDirectory = foundFiles[directory]; const beforeGroup = filesInDirectory.filter((p) => !!p.packageManager); const groupedFiles = groupBy(beforeGroup, 'packageManager'); for (const packageManager of Object.keys(groupedFiles)) { const filesPerPackageManager = groupedFiles[packageManager]; if (filesPerPackageManager.length <= 1) { const shouldSkip =