snyk 1.812.0 → 1.816.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -168,7 +168,7 @@ snyk --help
168
168
 
169
169
  See the [full Snyk CLI help](./help/cli-commands).
170
170
 
171
- ## Authorization
171
+ ## Authenticating Snyk CLI
172
172
 
173
173
  Snyk CLI depends on [Snyk.io](https://snyk.io) APIs. Connect your Snyk CLI with [Snyk.io](https://snyk.io) by running:
174
174
 
@@ -176,6 +176,12 @@ Snyk CLI depends on [Snyk.io](https://snyk.io) APIs. Connect your Snyk CLI with
176
176
  snyk auth
177
177
  ```
178
178
 
179
+ ## Setting up language support
180
+
181
+ Depending on your project's language, you might need to setup your language environment before using Snyk.
182
+
183
+ See our [Language Support documentation](https://support.snyk.io/hc/en-us/articles/360020352437-Language-support-summary).
184
+
179
185
  ## Scanning your project
180
186
 
181
187
  If you are already in a folder with a supported project, start by running:
@@ -1910,23 +1910,49 @@ function extractReportingDescriptor(results) {
1910
1910
  if (tool[issue.id]) {
1911
1911
  return;
1912
1912
  }
1913
+ // custom rules may not have some of these fields so we check them first
1914
+ const fullDescriptionText = issue.subType
1915
+ ? `${upperFirst(issue.severity)} severity - ${issue.subType}`
1916
+ : `${upperFirst(issue.severity)} severity`;
1917
+ const issueText = issue.iacDescription.issue
1918
+ ? `The issue is... \n${issue.iacDescription.issue}\n\n`
1919
+ : '';
1920
+ const issueMarkdown = issue.iacDescription.issue
1921
+ ? `**The issue is...** \n${issue.iacDescription.issue}\n\n`
1922
+ : '';
1923
+ const impactText = issue.iacDescription.impact
1924
+ ? ` The impact of this is... \n ${issue.iacDescription.impact}\n\n`
1925
+ : '';
1926
+ const impactMarkdown = issue.iacDescription.impact
1927
+ ? ` **The impact of this is...** \n ${issue.iacDescription.impact}\n\n`
1928
+ : '';
1929
+ const resolveText = issue.iacDescription.resolve
1930
+ ? ` You can resolve this by... \n${issue.iacDescription.resolve}`
1931
+ : '';
1932
+ const resolveMarkdown = issue.iacDescription.resolve
1933
+ ? ` **You can resolve this by...** \n${issue.iacDescription.resolve}`
1934
+ : '';
1935
+ const tags = ['security'];
1936
+ if (issue.subType) {
1937
+ tags.push(issue.subType);
1938
+ }
1913
1939
  tool[issue.id] = {
1914
1940
  id: issue.id,
1915
1941
  shortDescription: {
1916
1942
  text: `${upperFirst(issue.severity)} severity - ${issue.title}`,
1917
1943
  },
1918
1944
  fullDescription: {
1919
- text: `${upperFirst(issue.severity)} severity - ${issue.subType}`,
1945
+ text: fullDescriptionText,
1920
1946
  },
1921
1947
  help: {
1922
- text: `The issue is... \n${issue.iacDescription.issue}\n\n The impact of this is... \n ${issue.iacDescription.impact}\n\n You can resolve this by... \n${issue.iacDescription.resolve}`.replace(/^\s+/g, ''),
1923
- markdown: `**The issue is...** \n${issue.iacDescription.issue}\n\n **The impact of this is...** \n ${issue.iacDescription.impact}\n\n **You can resolve this by...** \n${issue.iacDescription.resolve}`.replace(/^\s+/g, ''),
1948
+ text: `${issueText}${impactText}${resolveText}`.replace(/^\s+/g, ''),
1949
+ markdown: `${issueMarkdown}${impactMarkdown}${resolveMarkdown}`.replace(/^\s+/g, ''),
1924
1950
  },
1925
1951
  defaultConfiguration: {
1926
1952
  level: getIssueLevel(issue.severity),
1927
1953
  },
1928
1954
  properties: {
1929
- tags: ['security', `${issue.subType}`],
1955
+ tags,
1930
1956
  documentation: issue.documentation,
1931
1957
  },
1932
1958
  };
@@ -1937,10 +1963,14 @@ exports.extractReportingDescriptor = extractReportingDescriptor;
1937
1963
  function mapIacTestResponseToSarifResults(issues) {
1938
1964
  return issues.map(({ targetPath, issue }) => {
1939
1965
  const hasLineNumber = issue.lineNumber && issue.lineNumber >= 0;
1966
+ // custom rules may not have some of these fields so we check them first
1967
+ const affectingText = issue.subType
1968
+ ? ` affecting the ${issue.subType}`
1969
+ : '';
1940
1970
  return {
1941
1971
  ruleId: issue.id,
1942
1972
  message: {
1943
- text: `This line contains a potential ${issue.severity} severity misconfiguration affecting the ${issue.subType}`,
1973
+ text: `This line contains a potential ${issue.severity} severity misconfiguration${affectingText}`,
1944
1974
  },
1945
1975
  locations: [
1946
1976
  {
@@ -4043,7 +4073,9 @@ exports.getExtraProjectCount = getExtraProjectCount;
4043
4073
  Object.defineProperty(exports, "__esModule", ({ value: true }));
4044
4074
  exports.getMultiPluginResult = void 0;
4045
4075
  const cloneDeep = __webpack_require__(83465);
4046
- const path = __webpack_require__(85622);
4076
+ const pathLib = __webpack_require__(85622);
4077
+ const sortBy = __webpack_require__(58254);
4078
+ const groupBy = __webpack_require__(20276);
4047
4079
  const cliInterface = __webpack_require__(65266);
4048
4080
  const chalk_1 = __webpack_require__(32589);
4049
4081
  const theme_1 = __webpack_require__(86988);
@@ -4053,14 +4085,21 @@ const get_single_plugin_result_1 = __webpack_require__(8598);
4053
4085
  const convert_single_splugin_res_to_multi_custom_1 = __webpack_require__(99695);
4054
4086
  const convert_multi_plugin_res_to_multi_custom_1 = __webpack_require__(23110);
4055
4087
  const errors_1 = __webpack_require__(55191);
4088
+ const yarn_workspaces_parser_1 = __webpack_require__(27326);
4056
4089
  const debug = debugModule('snyk-test');
4057
4090
  async function getMultiPluginResult(root, options, targetFiles) {
4091
+ var _a;
4058
4092
  const allResults = [];
4059
4093
  const failedResults = [];
4060
- for (const targetFile of targetFiles) {
4094
+ // process any yarn workspaces first
4095
+ // the files need to be proceeded together as they provide context to each other
4096
+ const { scannedProjects, unprocessedFiles, } = await processYarnWorkspacesProjects(root, options, targetFiles);
4097
+ allResults.push(...scannedProjects);
4098
+ // process the rest 1 by 1 sent to relevant plugins
4099
+ for (const targetFile of unprocessedFiles) {
4061
4100
  const optionsClone = cloneDeep(options);
4062
- optionsClone.file = path.relative(root, targetFile);
4063
- optionsClone.packageManager = detect_1.detectPackageManagerFromFile(path.basename(targetFile));
4101
+ optionsClone.file = pathLib.relative(root, targetFile);
4102
+ optionsClone.packageManager = detect_1.detectPackageManagerFromFile(pathLib.basename(targetFile));
4064
4103
  try {
4065
4104
  const inspectRes = await get_single_plugin_result_1.getSinglePluginResult(root, optionsClone, optionsClone.file);
4066
4105
  let resultWithScannedProjects;
@@ -4077,14 +4116,15 @@ async function getMultiPluginResult(root, options, targetFiles) {
4077
4116
  options.projectNames = resultWithScannedProjects.scannedProjects.map((scannedProject) => { var _a; return (_a = scannedProject === null || scannedProject === void 0 ? void 0 : scannedProject.depTree) === null || _a === void 0 ? void 0 : _a.name; });
4078
4117
  allResults.push(...pluginResultWithCustomScannedProjects.scannedProjects);
4079
4118
  }
4080
- catch (err) {
4119
+ catch (error) {
4120
+ const errMessage = (_a = error.message) !== null && _a !== void 0 ? _a : 'Something went wrong getting dependencies';
4081
4121
  // TODO: propagate this all the way back and include in --json output
4082
4122
  failedResults.push({
4083
4123
  targetFile,
4084
- error: err,
4085
- errMessage: err.message || 'Something went wrong getting dependencies',
4124
+ error,
4125
+ errMessage: errMessage,
4086
4126
  });
4087
- debug(chalk_1.default.bold.red(`\n${theme_1.icon.ISSUE} Failed to get dependencies for ${targetFile}\nERROR: ${err.message}\n`));
4127
+ debug(chalk_1.default.bold.red(`\n${theme_1.icon.ISSUE} Failed to get dependencies for ${targetFile}\nERROR: ${errMessage}\n`));
4088
4128
  }
4089
4129
  }
4090
4130
  if (!allResults.length) {
@@ -4099,6 +4139,44 @@ async function getMultiPluginResult(root, options, targetFiles) {
4099
4139
  };
4100
4140
  }
4101
4141
  exports.getMultiPluginResult = getMultiPluginResult;
4142
+ async function processYarnWorkspacesProjects(root, options, targetFiles) {
4143
+ try {
4144
+ const { scannedProjects } = await yarn_workspaces_parser_1.processYarnWorkspaces(root, {
4145
+ strictOutOfSync: options.strictOutOfSync,
4146
+ dev: options.dev,
4147
+ }, targetFiles);
4148
+ const unprocessedFiles = filterOutProcessedWorkspaces(scannedProjects, targetFiles);
4149
+ return { scannedProjects, unprocessedFiles };
4150
+ }
4151
+ catch (e) {
4152
+ debug('Error during detecting or processing Yarn Workspaces: ', e);
4153
+ return { scannedProjects: [], unprocessedFiles: targetFiles };
4154
+ }
4155
+ }
4156
+ function filterOutProcessedWorkspaces(scannedProjects, allTargetFiles) {
4157
+ const mapped = allTargetFiles.map((p) => ({ path: p, ...pathLib.parse(p) }));
4158
+ const sorted = sortBy(mapped, 'dir');
4159
+ const targetFilesByDirectory = groupBy(sorted, 'dir');
4160
+ const scanned = scannedProjects.map((p) => p.targetFile);
4161
+ const targetFiles = [];
4162
+ for (const directory of Object.keys(targetFilesByDirectory)) {
4163
+ for (const targetFile of targetFilesByDirectory[directory]) {
4164
+ const { base, path } = targetFile;
4165
+ // any non yarn workspace files should be scanned
4166
+ if (!['package.json', 'yarn.lock'].includes(base)) {
4167
+ targetFiles.push(path);
4168
+ continue;
4169
+ }
4170
+ // check if Node manifest has already been processed a part or a workspace
4171
+ const packageJsonFileName = pathLib.join(directory, 'package.json');
4172
+ const alreadyScanned = scanned.some((f) => packageJsonFileName.endsWith(f));
4173
+ if (!alreadyScanned) {
4174
+ targetFiles.push(path);
4175
+ }
4176
+ }
4177
+ }
4178
+ return targetFiles;
4179
+ }
4102
4180
 
4103
4181
 
4104
4182
  /***/ }),
@@ -4370,25 +4448,24 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
4370
4448
  exports.packageJsonBelongsToWorkspace = exports.getWorkspacesMap = exports.processYarnWorkspaces = void 0;
4371
4449
  const baseDebug = __webpack_require__(15158);
4372
4450
  const pathUtil = __webpack_require__(85622);
4373
- // import * as _ from 'lodash';
4374
4451
  const sortBy = __webpack_require__(58254);
4375
4452
  const groupBy = __webpack_require__(20276);
4376
4453
  const micromatch = __webpack_require__(70850);
4377
4454
  const debug = baseDebug('snyk-yarn-workspaces');
4378
4455
  const lockFileParser = __webpack_require__(423);
4379
- const errors_1 = __webpack_require__(55191);
4380
4456
  const get_file_contents_1 = __webpack_require__(84210);
4457
+ const errors_1 = __webpack_require__(55191);
4381
4458
  async function processYarnWorkspaces(root, settings, targetFiles) {
4382
4459
  // the order of yarnTargetFiles folders is important
4383
4460
  // must have the root level most folders at the top
4384
4461
  const mappedAndFiltered = targetFiles
4385
4462
  .map((p) => ({ path: p, ...pathUtil.parse(p) }))
4386
- .filter((res) => ['package.json'].includes(res.base));
4463
+ .filter((res) => ['package.json', 'yarn.lock'].includes(res.base));
4387
4464
  const sorted = sortBy(mappedAndFiltered, 'dir');
4388
4465
  const grouped = groupBy(sorted, 'dir');
4389
4466
  const yarnTargetFiles = grouped;
4390
4467
  debug(`Processing potential Yarn workspaces (${targetFiles.length})`);
4391
- if (Object.keys(yarnTargetFiles).length === 0) {
4468
+ if (settings.yarnWorkspaces && Object.keys(yarnTargetFiles).length === 0) {
4392
4469
  throw errors_1.NoSupportedManifestsFoundError([root]);
4393
4470
  }
4394
4471
  let yarnWorkspacesMap = {};
@@ -4403,6 +4480,7 @@ async function processYarnWorkspaces(root, settings, targetFiles) {
4403
4480
  let rootWorkspaceManifestContent = {};
4404
4481
  // the folders must be ordered highest first
4405
4482
  for (const directory of Object.keys(yarnTargetFiles)) {
4483
+ debug(`Processing ${directory} as a potential Yarn workspace`);
4406
4484
  let isYarnWorkspacePackage = false;
4407
4485
  let isRootPackageJson = false;
4408
4486
  const packageJsonFileName = pathUtil.join(directory, 'package.json');
@@ -4425,7 +4503,11 @@ async function processYarnWorkspaces(root, settings, targetFiles) {
4425
4503
  rootWorkspaceManifestContent = JSON.parse(packageJson.content);
4426
4504
  }
4427
4505
  }
4428
- if (isYarnWorkspacePackage || isRootPackageJson) {
4506
+ if (!(isYarnWorkspacePackage || isRootPackageJson)) {
4507
+ debug(`${packageJsonFileName} is not part of any detected workspace, skipping`);
4508
+ continue;
4509
+ }
4510
+ try {
4429
4511
  const rootDir = isYarnWorkspacePackage
4430
4512
  ? pathUtil.dirname(yarnWorkspacesFilesMap[packageJsonFileName].root)
4431
4513
  : pathUtil.dirname(packageJsonFileName);
@@ -4452,8 +4534,11 @@ async function processYarnWorkspaces(root, settings, targetFiles) {
4452
4534
  };
4453
4535
  result.scannedProjects.push(project);
4454
4536
  }
4455
- else {
4456
- debug(`${packageJsonFileName} is not part of any detected workspace, skipping`);
4537
+ catch (e) {
4538
+ if (settings.yarnWorkspaces) {
4539
+ throw e;
4540
+ }
4541
+ debug(`Error process workspace: ${packageJsonFileName}. ERROR: ${e}`);
4457
4542
  }
4458
4543
  }
4459
4544
  if (!result.scannedProjects.length) {
@@ -6536,7 +6621,7 @@ async function assembleLocalPayloads(root, options) {
6536
6621
  }
6537
6622
  debug('getDepsFromPlugin returned failed results, cannot run test/monitor', failedResults);
6538
6623
  if (options['fail-fast']) {
6539
- throw new errors_1.FailedToRunTestError('Your test request could not be completed. Please email support@snyk.io');
6624
+ throw new errors_1.FailedToRunTestError(errors_1.errorMessageWithRetry('Your test request could not be completed.'));
6540
6625
  }
6541
6626
  }
6542
6627
  analytics.add('pluginName', deps.plugin.name);