UNPKG

snyk

Version:

snyk library and cli utility

1,225 lines (1,136 loc) • 262 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 check_paths_1 = __webpack_require__(94501); const theme = __webpack_require__(86988); const types_1 = __webpack_require__(94055); const config_1 = __webpack_require__(25425); 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'); const appVulnsReleaseWarningMsg = `${theme.icon.WARNING} Important: Beginning January 24th, 2023, application dependencies in container images will be scanned by default when using the snyk container test/monitor commands. If you are using Snyk in a CI pipeline, action may be required. Read https://snyk.io/blog/securing-container-applications-using-the-snyk-cli/ for more info.`; // 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) { check_paths_1.checkOSSPaths(paths, options); } if (options.docker && options['remote-repo-url']) { throw new Error('`--remote-repo-url` is not supported for container scans'); } // TODO remove 'app-vulns' options and warning message once // https://github.com/snyk/cli/pull/3433 is merged if (options.docker) { if (!options['app-vulns'] || options['exclude-app-vulns']) { options['exclude-app-vulns'] = true; } // we can't print the warning message with JSON output as that would make // the JSON output invalid. if (!options['app-vulns'] && !options['json']) { console.log(theme.color.status.warn(appVulnsReleaseWarningMsg)); } } // 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, contributors); 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); } 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; } } /***/ }), /***/ 94501: /***/ ((__unused_webpack_module, exports, __webpack_require__) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.checkOSSPaths = void 0; const errors_1 = __webpack_require__(55191); const detect_1 = __webpack_require__(45318); // Throw error if user specifies package file name as part of path, // and if user specifies multiple paths and used project-name option. function checkOSSPaths(paths, options) { let count = 0; for (const path of paths) { if (typeof path === 'string' && detect_1.isPathToPackageFile(path)) { throw errors_1.MissingTargetFileError(path); } else if (typeof path === 'string') { if (++count > 1 && options['project-name']) { throw new errors_1.UnsupportedOptionCombinationError([ 'multiple paths', 'project-name', ]); } } } } exports.checkOSSPaths = checkOSSPaths; /***/ }), /***/ 55203: /***/ ((__unused_webpack_module, exports, __webpack_require__) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getBase64Encoding = exports.getCodeClientProxyUrl = void 0; const config_1 = __webpack_require__(25425); const user_config_1 = __webpack_require__(28137); function getCodeClientProxyUrl() { const url = new URL(config_1.default.API); const domain = url.origin; return (config_1.default.CODE_CLIENT_PROXY_URL || domain.replace(/\/\/(ap[pi]\.)?/, '//deeproxy.')); } exports.getCodeClientProxyUrl = getCodeClientProxyUrl; function getBase64Encoding(enabled = user_config_1.config.get('use-base64-encoding')) { if (enabled) { return enabled.toLowerCase() === 'true'; } return false; } exports.getBase64Encoding = getBase64Encoding; /***/ }), /***/ 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; /***/ }), /***/ 73399: /***/ ((__unused_webpack_module, exports) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.hasUnknownVersions = void 0; function hasUnknownVersions(depGraph) { if (!depGraph) { return false; } for (const pkg of depGraph.getPkgs()) { if (pkg.version === 'unknown') { return true; } } return false; } exports.hasUnknownVersions = hasUnknownVersions; /***/ }), /***/ 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__(25425); 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, contributors) { 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, contributors); return [monitorResults, errors]; } exports.monitorEcosystem = monitorEcosystem; async function selectAndExecuteMonitorStrategy(ecosystem, scanResultsByPath, options, contributors) { return common_1.isUnmanagedEcosystem(ecosystem) ? await resolve_monitor_facts_1.resolveAndMonitorFacts(scanResultsByPath, options, contributors) : 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, contributors) { 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, contributors); 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.resolveAndTestFactsRegistry = exports.resolveAndTestFactsUnmanagedDeps = 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); const feature_flags_1 = __webpack_require__(63011); const utils_1 = __webpack_require__(97875); const common_1 = __webpack_require__(70527); async function resolveAndTestFacts(ecosystem, scans, options) { const unmanagedDepsOverride = process.env.USE_UNMANAGED_DEPS; const featureFlagEnabled = await feature_flags_1.hasFeatureFlag('snykNewUnmanagedTest', options); return featureFlagEnabled || (unmanagedDepsOverride === null || unmanagedDepsOverride === void 0 ? void 0 : unmanagedDepsOverride.toLowerCase()) === 'true' ? resolveAndTestFactsUnmanagedDeps(scans, options) : resolveAndTestFactsRegistry(ecosystem, scans, options); } exports.resolveAndTestFacts = resolveAndTestFacts; async function submitHashes(hashes, orgId) { const response = await polling_test_1.createDepGraph(hashes, orgId); return response.data.id; } async function pollDepGraphAttributes(id, orgId) { const maxIntervalMs = 60000; const minIntervalMs = 5000; const maxAttempts = 31; // Corresponds to 25.5 minutes // Loop until we receive a response that is not in progress, // or we receive something else than http status code 200. for (let i = 1; i <= maxAttempts; i++) { const graph = await polling_test_1.getDepGraph(id, orgId); if (graph.data.attributes.in_progress) { const pollInterval = Math.max(maxIntervalMs, minIntervalMs * i); await common_1.sleep(pollInterval * i); continue; } return graph.data.attributes; } throw new Error('max retries reached'); } async function fetchIssues(start_time, dep_graph_data, component_details, orgId) { var _a, _b; const response = await polling_test_1.getIssues({ dep_graph: dep_graph_data, start_time, component_details, }, orgId); const issues = response.data.result.issues.map((issue) => { const converted = utils_1.convertToCamelCase(issue); converted.fixInfo = utils_1.convertToCamelCase(converted.fixInfo); return converted; }); const issuesData = utils_1.convertMapCasing(response.data.result.issues_data); const depGraphData = utils_1.convertDepGraph(response.data.result.dep_graph); const dependencyCount = (_b = (_a = response.data.result.dep_graph.graph.nodes.find((graphNode) => { return graphNode.node_id === 'root-node'; })) === null || _a === void 0 ? void 0 : _a.deps) === null || _b === void 0 ? void 0 : _b.length; const depsFilePaths = response.data.result.deps_file_paths; const fileSignaturesDetails = utils_1.convertMapCasing(response.data.result.file_signatures_details); return { issues, issuesData, depGraphData, dependencyCount, depsFilePaths, fileSignaturesDetails, }; } async function resolveAndTestFactsUnmanagedDeps(scans, options) { var _a, _b, _c, _d; const results = []; const errors = []; const packageManager = 'Unmanaged (C/C++)'; const displayTargetFile = ''; let orgId = options.org || ''; if (orgId === '') { const self = await utils_1.getSelf(); orgId = self.default_org_context; } 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 id = await submitHashes({ hashes: (_a = scanResult === null || scanResult === void 0 ? void 0 : scanResult.facts[0]) === null || _a === void 0 ? void 0 : _a.data }, orgId); const { start_time, dep_graph_data, component_details, } = await pollDepGraphAttributes(id, orgId); const { issues, issuesData, depGraphData, dependencyCount, depsFilePaths, fileSignaturesDetails, } = await fetchIssues(start_time, dep_graph_data, component_details, orgId); const issuesMap = new Map(); issues.forEach((i) => { issuesMap[i.issueId] = i; }); const vulnerabilities = []; for (const issuesDataKey in issuesData) { const pkgCoordinate = `${(_b = issuesMap[issuesDataKey]) === null || _b === void 0 ? void 0 : _b.pkgName}@${(_c = issuesMap[issuesDataKey]) === null || _c === void 0 ? void 0 : _c.pkgVersion}`; const issueData = issuesData[issuesDataKey]; issueData.from = [pkgCoordinate]; issueData.name = pkgCoordinate; issueData.packageManager = packageManager; issueData.version = (_d = issuesMap[issuesDataKey]) === null || _d === void 0 ? void 0 : _d.pkgVersion; issueData.upgradePath = [false]; issueData.isPatchable = false; vulnerabilities.push(issueData); } const policy = await policy_1.findAndLoadPolicy(path, 'cpp', options); const [issuesFiltered, issuesDataFiltered] = policy_2.filterIgnoredIssues(issues, issuesData, policy); results.push({ issues: issuesFiltered, issuesData: issuesDataFiltered, depGraphData, depsFilePaths, fileSignaturesDetails, vulnerabilities, path, dependencyCount, packageManager, displayTargetFile, }); } 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.resolveAndTestFactsUnmanagedDeps = resolveAndTestFactsUnmanagedDeps; async function resolveAndTestFactsRegistry(ecosystem, scans, options) { var _a, _b, _c, _d, _e, _f; const results = []; const errors = []; const packageManager = 'Unmanaged (C/C++)'; const displayTargetFile = ''; 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); const issuesMap = new Map(); response.issues.forEach((i) => { issuesMap[i.issueId] = i; }); const vulnerabilities = []; for (const issuesDataKey in response.issuesData) { if (issuesMap[issuesDataKey]) { const issueData = response.issuesData[issuesDataKey]; const pkgCoordinate = `${issuesMap[issuesDataKey].pkgName}@${issuesMap[issuesDataKey].pkgVersion}`; issueData.from = [pkgCoordinate]; issueData.name = pkgCoordinate; issueData.packageManager = packageManager; issueData.version = (_a = issuesMap[issuesDataKey]) === null || _a === void 0 ? void 0 : _a.pkgVersion; issueData.upgradePath = [false]; issueData.isPatchable = false; vulnerabilities.push(issueData); } } const dependencyCount = (_f = (_e = (_d = (_c = (_b = response === null || response === void 0 ? void 0 : response.depGraphData) === null || _b === void 0 ? void 0 : _b.graph) === null || _c === void 0 ? void 0 : _c.nodes) === null || _d === void 0 ? void 0 : _d.find((graphNode) => { return graphNode.nodeId === 'root-node'; })) === null || _e === void 0 ? void 0 : _e.deps) === null || _f === void 0 ? void 0 : _f.length; 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, vulnerabilities, path, dependencyCount, packageManager, displayTargetFile, }); } 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.resolveAndTestFactsRegistry = resolveAndTestFactsRegistry; /***/ }), /***/ 60937: /***/ ((__unused_webpack_module, exports, __webpack_require__) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.selectAndExecuteTestStrategy = e