snyk 1.992.0 → 1.993.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.
Files changed (21) hide show
  1. package/dist/cli/895.index.js +2 -1
  2. package/dist/cli/895.index.js.map +1 -1
  3. package/dist/cli/917.index.js +834 -793
  4. package/dist/cli/917.index.js.map +1 -1
  5. package/dist/cli/commands/test/iac/local-execution/assert-iac-options-flag.d.ts +1 -0
  6. package/dist/cli/commands/test/iac/v2/assert-iac-options.d.ts +2 -0
  7. package/dist/lib/iac/test/v2/index.d.ts +1 -1
  8. package/dist/lib/iac/test/v2/{setup/local-cache → local-cache}/index.d.ts +5 -3
  9. package/dist/lib/iac/test/v2/{setup/local-cache → local-cache}/policy-engine/constants/index.d.ts +0 -0
  10. package/dist/lib/iac/test/v2/{setup/local-cache → local-cache}/policy-engine/constants/utils.d.ts +0 -0
  11. package/dist/lib/iac/test/v2/{setup/local-cache → local-cache}/policy-engine/download.d.ts +2 -2
  12. package/dist/lib/iac/test/v2/{setup/local-cache → local-cache}/policy-engine/index.d.ts +1 -1
  13. package/dist/lib/iac/test/v2/{setup/local-cache → local-cache}/policy-engine/lookup-local.d.ts +2 -2
  14. package/dist/lib/iac/test/v2/{setup/local-cache → local-cache}/rules-bundle/constants.d.ts +0 -0
  15. package/dist/lib/iac/test/v2/{setup/local-cache → local-cache}/rules-bundle/download.d.ts +2 -2
  16. package/dist/lib/iac/test/v2/{setup/local-cache → local-cache}/rules-bundle/index.d.ts +1 -1
  17. package/dist/lib/iac/test/v2/{setup/local-cache → local-cache}/rules-bundle/lookup-local.d.ts +2 -2
  18. package/dist/lib/iac/test/v2/{setup/local-cache → local-cache}/utils.d.ts +1 -1
  19. package/dist/lib/iac/test/v2/types.d.ts +1 -0
  20. package/package.json +1 -1
  21. package/dist/lib/iac/test/v2/setup/index.d.ts +0 -5
@@ -2229,6 +2229,56 @@ class DefaultGitRepositoryFinder {
2229
2229
  }
2230
2230
 
2231
2231
 
2232
+ /***/ }),
2233
+
2234
+ /***/ 15335:
2235
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
2236
+
2237
+ "use strict";
2238
+
2239
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
2240
+ exports.assertIacV2Options = void 0;
2241
+ const assert_iac_options_flag_1 = __webpack_require__(33111);
2242
+ const keys = [
2243
+ 'debug',
2244
+ 'v',
2245
+ 'version',
2246
+ 'h',
2247
+ 'help',
2248
+ 'q',
2249
+ 'quiet',
2250
+ 'org',
2251
+ 'insecure',
2252
+ 'severityThreshold',
2253
+ 'json',
2254
+ 'sarif',
2255
+ 'json-file-output',
2256
+ 'sarif-file-output',
2257
+ 'scan',
2258
+ 'experimental',
2259
+ 'var-file',
2260
+ // PolicyOptions
2261
+ 'ignore-policy',
2262
+ 'policy-path',
2263
+ ];
2264
+ const allowed = new Set(keys);
2265
+ function assertIacV2Options(options) {
2266
+ // We process the process.argv so we don't get default values.
2267
+ for (const key of Object.keys(options)) {
2268
+ // The _ property is a special case that contains non
2269
+ // flag strings passed to the command line (usually files)
2270
+ // and `iac` is the command provided.
2271
+ if (key !== '_' && key !== 'iac' && !allowed.has(key)) {
2272
+ throw new assert_iac_options_flag_1.FlagError(key);
2273
+ }
2274
+ }
2275
+ if (options.scan) {
2276
+ assert_iac_options_flag_1.assertTerraformPlanModes(options.scan);
2277
+ }
2278
+ }
2279
+ exports.assertIacV2Options = assertIacV2Options;
2280
+
2281
+
2232
2282
  /***/ }),
2233
2283
 
2234
2284
  /***/ 2460:
@@ -2250,7 +2300,9 @@ const local_execution_1 = __webpack_require__(89627);
2250
2300
  const scan_1 = __webpack_require__(50277);
2251
2301
  const index_1 = __webpack_require__(55935);
2252
2302
  const policy_1 = __webpack_require__(32615);
2303
+ const assert_iac_options_1 = __webpack_require__(15335);
2253
2304
  async function test(paths, options) {
2305
+ assert_iac_options_1.assertIacV2Options(options);
2254
2306
  const testConfig = await prepareTestConfig(paths, options);
2255
2307
  const { orgSettings } = testConfig;
2256
2308
  const testSpinner = output_1.buildSpinner(options);
@@ -2271,6 +2323,7 @@ async function test(paths, options) {
2271
2323
  }
2272
2324
  exports.test = test;
2273
2325
  async function prepareTestConfig(paths, options) {
2326
+ var _a;
2274
2327
  const iacCachePath = pathLib.join(scan_1.systemCachePath, 'iac');
2275
2328
  const org = options.org || config_1.default.org;
2276
2329
  const orgSettings = await get_iac_org_settings_1.getIacOrgSettings(org);
@@ -2279,6 +2332,7 @@ async function prepareTestConfig(paths, options) {
2279
2332
  const remoteRepoUrl = index_1.getFlag(options, 'remote-repo-url');
2280
2333
  const attributes = parseAttributes(options);
2281
2334
  const policy = await policy_1.findAndLoadPolicy(process.cwd(), 'iac', options);
2335
+ const scan = (_a = options.scan) !== null && _a !== void 0 ? _a : 'resource-changes';
2282
2336
  return {
2283
2337
  paths,
2284
2338
  iacCachePath,
@@ -2293,6 +2347,7 @@ async function prepareTestConfig(paths, options) {
2293
2347
  targetName,
2294
2348
  remoteRepoUrl,
2295
2349
  policy: policy === null || policy === void 0 ? void 0 : policy.toString(),
2350
+ scan,
2296
2351
  };
2297
2352
  }
2298
2353
  function parseAttributes(options) {
@@ -4276,10 +4331,10 @@ exports.SnykIacTestError = SnykIacTestError;
4276
4331
 
4277
4332
  Object.defineProperty(exports, "__esModule", ({ value: true }));
4278
4333
  exports.test = void 0;
4279
- const setup_1 = __webpack_require__(88929);
4280
4334
  const scan_1 = __webpack_require__(50277);
4335
+ const local_cache_1 = __webpack_require__(68081);
4281
4336
  async function test(testConfig) {
4282
- const { policyEnginePath, rulesBundlePath } = await setup_1.setup(testConfig);
4337
+ const { policyEnginePath, rulesBundlePath } = await local_cache_1.initLocalCache(testConfig);
4283
4338
  return scan_1.scan(testConfig, policyEnginePath, rulesBundlePath);
4284
4339
  }
4285
4340
  exports.test = test;
@@ -4471,975 +4526,961 @@ function orgSettingsToIgnoreSettings(orgSettings) {
4471
4526
 
4472
4527
  /***/ }),
4473
4528
 
4474
- /***/ 99687:
4529
+ /***/ 68081:
4475
4530
  /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
4476
4531
 
4477
4532
  "use strict";
4478
4533
 
4479
4534
  Object.defineProperty(exports, "__esModule", ({ value: true }));
4480
- exports.FoundIssuesError = exports.NoLoadableInputError = exports.NoSuccessfulScansError = exports.buildOutput = void 0;
4481
- const os_1 = __webpack_require__(12087);
4482
- const json_1 = __webpack_require__(71909);
4483
- const types_1 = __webpack_require__(55246);
4484
- const text_1 = __webpack_require__(86166);
4485
- const json_2 = __webpack_require__(27019);
4486
- const types_2 = __webpack_require__(94820);
4487
- const sarif_1 = __webpack_require__(87999);
4535
+ exports.initLocalCache = void 0;
4536
+ const rules_bundle_1 = __webpack_require__(51897);
4537
+ const policy_engine_1 = __webpack_require__(90474);
4538
+ const file_utils_1 = __webpack_require__(52761);
4488
4539
  const errors_1 = __webpack_require__(55191);
4489
- const strip_ansi_1 = __webpack_require__(76003);
4490
- const path = __webpack_require__(85622);
4491
- const error_utils_1 = __webpack_require__(36401);
4492
- const output_1 = __webpack_require__(39313);
4493
- function buildOutput({ scanResult, testSpinner, orgSettings, options, }) {
4494
- if (scanResult.results) {
4495
- testSpinner === null || testSpinner === void 0 ? void 0 : testSpinner.succeed(text_1.spinnerSuccessMessage);
4496
- }
4497
- else {
4498
- testSpinner === null || testSpinner === void 0 ? void 0 : testSpinner.stop();
4540
+ const local_cache_1 = __webpack_require__(50089);
4541
+ async function initLocalCache(testConfig) {
4542
+ try {
4543
+ await file_utils_1.createDirIfNotExists(testConfig.iacCachePath);
4544
+ const policyEnginePath = await policy_engine_1.initPolicyEngine(testConfig);
4545
+ const rulesBundlePath = await rules_bundle_1.initRulesBundle(testConfig);
4546
+ return { policyEnginePath, rulesBundlePath };
4499
4547
  }
4500
- const { responseData, jsonData, sarifData } = buildTestCommandResultData({
4501
- scanResult,
4502
- orgSettings,
4503
- options,
4504
- });
4505
- if (options.json || options.sarif) {
4506
- return types_1.TestCommandResult.createJsonTestCommandResult(responseData, jsonData, sarifData);
4548
+ catch (err) {
4549
+ throw err instanceof errors_1.CustomError ? err : new local_cache_1.FailedToInitLocalCacheError();
4507
4550
  }
4508
- return types_1.TestCommandResult.createHumanReadableTestCommandResult(responseData, jsonData, sarifData);
4509
4551
  }
4510
- exports.buildOutput = buildOutput;
4511
- function buildTestCommandResultData({ scanResult, orgSettings, options, }) {
4512
- var _a, _b, _c, _d, _e;
4513
- const projectName = (_c = (_b = (_a = scanResult.results) === null || _a === void 0 ? void 0 : _a.metadata) === null || _b === void 0 ? void 0 : _b.projectName) !== null && _c !== void 0 ? _c : path.basename(process.cwd());
4514
- const jsonData = json_2.jsonStringifyLargeObject(json_1.convertEngineToJsonResults({
4515
- results: scanResult,
4516
- projectName,
4517
- orgSettings,
4518
- }));
4519
- const sarifData = json_2.jsonStringifyLargeObject(sarif_1.convertEngineToSarifResults(scanResult));
4520
- assertHasSuccessfulScans(scanResult, { json: jsonData, sarif: sarifData }, options);
4521
- let responseData;
4522
- if (options.json) {
4523
- responseData = jsonData;
4524
- }
4525
- else if (options.sarif) {
4526
- responseData = sarifData;
4527
- }
4528
- else {
4529
- responseData = buildTextOutput({
4530
- scanResult,
4531
- projectName,
4532
- orgSettings,
4533
- options,
4534
- });
4535
- }
4536
- const hasVulnerabilities = !!((_e = (_d = scanResult.results) === null || _d === void 0 ? void 0 : _d.vulnerabilities) === null || _e === void 0 ? void 0 : _e.length);
4537
- if (hasVulnerabilities) {
4538
- throw new FoundIssuesError({
4539
- response: responseData,
4540
- json: jsonData,
4541
- sarif: sarifData,
4542
- });
4552
+ exports.initLocalCache = initLocalCache;
4553
+
4554
+
4555
+ /***/ }),
4556
+
4557
+ /***/ 64895:
4558
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
4559
+
4560
+ "use strict";
4561
+
4562
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
4563
+ exports.policyEngineChecksum = exports.policyEngineFileName = exports.policyEngineReleaseVersion = void 0;
4564
+ const utils_1 = __webpack_require__(1728);
4565
+ /**
4566
+ * The Policy Engine release version associated with this Snyk CLI version.
4567
+ */
4568
+ exports.policyEngineReleaseVersion = utils_1.policyEngineVersion;
4569
+ /**
4570
+ * The Policy Engine executable's file name.
4571
+ */
4572
+ exports.policyEngineFileName = utils_1.formatPolicyEngineFileName(exports.policyEngineReleaseVersion);
4573
+ exports.policyEngineChecksum = utils_1.getChecksum(exports.policyEngineFileName);
4574
+
4575
+
4576
+ /***/ }),
4577
+
4578
+ /***/ 1728:
4579
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
4580
+
4581
+ "use strict";
4582
+
4583
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
4584
+ exports.getChecksum = exports.formatPolicyEngineFileName = exports.policyEngineVersion = void 0;
4585
+ const os = __webpack_require__(12087);
4586
+ const policyEngineChecksums = `20c1531abe769c623106d72158c7008904abbf5e9434c3e13ad1bbd0142c485b snyk-iac-test_0.24.0_Windows_x86_64.exe
4587
+ 3bc449f592a51e0cb3e1d7c8c4eeae8f65a6ffca3cbe1466ecb58e89138bf075 snyk-iac-test_0.24.0_Linux_x86_64
4588
+ 9efe44502e92a7b6011ab133349a1d59575773c78c5154642cb4b687aad5fa7e snyk-iac-test_0.24.0_Darwin_x86_64
4589
+ a0f577d1169532fa1056f5502e7481522520fc6259ce12f9d2877b87b4269bb0 snyk-iac-test_0.24.0_Windows_arm64.exe
4590
+ f519daf0bd505865a94ba37079f1109dd0177d645bf07c0bd5ceb1288da18b0c snyk-iac-test_0.24.0_Linux_arm64
4591
+ f6039356de00a6075714f8d703b4120fb41f8f6ada836f32fdb40d22a89230f2 snyk-iac-test_0.24.0_Darwin_arm64
4592
+ `;
4593
+ exports.policyEngineVersion = getPolicyEngineVersion();
4594
+ function formatPolicyEngineFileName(releaseVersion) {
4595
+ let platform = 'Linux';
4596
+ switch (os.platform()) {
4597
+ case 'darwin':
4598
+ platform = 'Darwin';
4599
+ break;
4600
+ case 'win32':
4601
+ platform = 'Windows';
4602
+ break;
4543
4603
  }
4544
- return { responseData, jsonData, sarifData };
4604
+ const arch = os.arch() === 'arm64' ? 'arm64' : 'x86_64';
4605
+ const execExt = os.platform() === 'win32' ? '.exe' : '';
4606
+ return `snyk-iac-test_${releaseVersion}_${platform}_${arch}${execExt}`;
4545
4607
  }
4546
- const SEPARATOR = '\n-------------------------------------------------------\n';
4547
- function buildTextOutput({ scanResult, projectName, orgSettings, options, }) {
4548
- let response = '';
4549
- const testData = text_1.formatSnykIacTestTestData(scanResult.results, projectName, orgSettings.meta.org);
4550
- response +=
4551
- os_1.EOL +
4552
- text_1.getIacDisplayedIssues(testData.resultsBySeverity, {
4553
- shouldShowLineNumbers: true,
4554
- });
4555
- if (scanResult.errors) {
4556
- const testFailures = scanResult.errors.map((error) => ({
4557
- filePath: error.fields.path,
4558
- failureReason: error.userMessage,
4559
- }));
4560
- response += os_1.EOL.repeat(2) + text_1.formatIacTestFailures(testFailures);
4561
- }
4562
- response += os_1.EOL;
4563
- response += SEPARATOR;
4564
- response += os_1.EOL;
4565
- response += text_1.formatIacTestSummary(testData);
4566
- response += os_1.EOL;
4567
- if (options.report) {
4568
- response += output_1.buildShareResultsSummary({
4569
- orgName: orgSettings.meta.org,
4570
- projectName,
4571
- options,
4572
- isIacCustomRulesEntitlementEnabled: false,
4573
- isIacShareCliResultsCustomRulesSupported: false,
4574
- });
4575
- response += os_1.EOL;
4576
- }
4577
- if (output_1.shouldPrintShareResultsTip(options)) {
4578
- response += SEPARATOR + os_1.EOL + text_1.shareResultsTip + os_1.EOL;
4608
+ exports.formatPolicyEngineFileName = formatPolicyEngineFileName;
4609
+ function getChecksum(policyEngineFileName) {
4610
+ const lines = policyEngineChecksums.split(/\r?\n/);
4611
+ const checksumsMap = new Map();
4612
+ for (const line of lines) {
4613
+ const [checksum, file] = line.split(/\s+/);
4614
+ if (file && checksum) {
4615
+ checksumsMap.set(file, checksum.trim());
4616
+ }
4579
4617
  }
4580
- return response;
4581
- }
4582
- function assertHasSuccessfulScans(scanResult, responseData, options) {
4583
- var _a, _b, _c;
4584
- const hasResources = !!((_b = (_a = scanResult.results) === null || _a === void 0 ? void 0 : _a.resources) === null || _b === void 0 ? void 0 : _b.length);
4585
- const hasErrors = !!((_c = scanResult.errors) === null || _c === void 0 ? void 0 : _c.length);
4586
- const hasSuccessfulScans = hasResources || !hasErrors;
4587
- if (!hasSuccessfulScans) {
4588
- const hasLoadableInput = scanResult.errors.some((error) => error.code !== types_2.IaCErrorCodes.NoLoadableInput);
4589
- throw hasLoadableInput
4590
- ? new NoSuccessfulScansError(responseData, scanResult.errors, options)
4591
- : new NoLoadableInputError(responseData, scanResult.errors, options);
4618
+ const policyEngineChecksum = checksumsMap.get(policyEngineFileName);
4619
+ if (!policyEngineChecksum) {
4620
+ // This is an internal error and technically it should never be thrown
4621
+ throw new Error(`Could not find checksum for ${policyEngineFileName}`);
4592
4622
  }
4623
+ return policyEngineChecksum;
4593
4624
  }
4594
- class NoSuccessfulScansError extends errors_1.FormattedCustomError {
4595
- constructor(responseData, errors, options) {
4596
- const firstErr = errors[0];
4597
- const isText = !options.json && !options.sarif;
4598
- const message = options.json
4599
- ? responseData.json
4600
- : options.sarif
4601
- ? responseData.sarif
4602
- : firstErr.message;
4603
- super(message, isText
4604
- ? text_1.formatIacTestFailures(errors.map((scanError) => ({
4605
- failureReason: scanError.userMessage,
4606
- filePath: scanError.fields.path,
4607
- })))
4608
- : strip_ansi_1.default(message));
4609
- this.code = firstErr.code;
4610
- this.strCode = firstErr.strCode;
4611
- this.json = isText ? responseData.json : message;
4612
- this.jsonStringifiedResults = responseData.json;
4613
- this.sarifStringifiedResults = responseData.sarif;
4614
- this.fields = firstErr.fields;
4615
- }
4616
- get path() {
4617
- var _a;
4618
- return (_a = this.fields) === null || _a === void 0 ? void 0 : _a.path;
4625
+ exports.getChecksum = getChecksum;
4626
+ function getPolicyEngineVersion() {
4627
+ const lines = policyEngineChecksums.split(/\r?\n/);
4628
+ if (lines.length == 0) {
4629
+ throw new Error('empty checksum');
4619
4630
  }
4620
- set path(path1) {
4621
- this.fields.path = path1;
4631
+ const line = lines.find((line) => line.length > 0);
4632
+ if (line === undefined) {
4633
+ throw new Error('empty checksum lines');
4622
4634
  }
4623
- }
4624
- exports.NoSuccessfulScansError = NoSuccessfulScansError;
4625
- class NoLoadableInputError extends NoSuccessfulScansError {
4626
- constructor(responseData, errors, options) {
4627
- super(responseData, errors, options);
4628
- (this.code = types_2.IaCErrorCodes.NoFilesToScanError),
4629
- (this.strCode = error_utils_1.getErrorStringCode(this.code));
4635
+ const parts = line.split(/\s+/);
4636
+ if (parts.length < 2) {
4637
+ throw new Error('invalid checksum line');
4630
4638
  }
4631
- }
4632
- exports.NoLoadableInputError = NoLoadableInputError;
4633
- class FoundIssuesError extends errors_1.CustomError {
4634
- constructor(responseData) {
4635
- super(responseData.response);
4636
- this.code = 'VULNS';
4637
- this.strCode = 'VULNS';
4638
- this.userMessage = responseData.response;
4639
- this.jsonStringifiedResults = responseData.json;
4640
- this.sarifStringifiedResults = responseData.sarif;
4639
+ const components = parts[1].split('_');
4640
+ if (components.length < 2) {
4641
+ throw new Error('invalid checksum file name');
4641
4642
  }
4643
+ return components[1];
4642
4644
  }
4643
- exports.FoundIssuesError = FoundIssuesError;
4644
4645
 
4645
4646
 
4646
4647
  /***/ }),
4647
4648
 
4648
- /***/ 87999:
4649
+ /***/ 58939:
4649
4650
  /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
4650
4651
 
4651
4652
  "use strict";
4652
4653
 
4653
4654
  Object.defineProperty(exports, "__esModule", ({ value: true }));
4654
- exports.convertEngineToSarifResults = void 0;
4655
- const url_1 = __webpack_require__(78835);
4656
- const marked_1 = __webpack_require__(30970);
4657
- const path = __webpack_require__(85622);
4658
- const upperFirst = __webpack_require__(90039);
4659
- const camelCase = __webpack_require__(76884);
4660
- const version_1 = __webpack_require__(38217);
4661
- const sarif_output_1 = __webpack_require__(5034);
4662
- const git_1 = __webpack_require__(82421);
4663
- // Used to reference the base path in results.
4664
- const PROJECT_ROOT_KEY = 'PROJECTROOT';
4665
- function convertEngineToSarifResults(scanResult) {
4666
- let repoRoot;
4655
+ exports.FailedToCachePolicyEngineError = exports.FailedToDownloadPolicyEngineError = exports.policyEngineUrl = exports.downloadPolicyEngine = void 0;
4656
+ const pathLib = __webpack_require__(85622);
4657
+ const crypto = __webpack_require__(76417);
4658
+ const createDebugLogger = __webpack_require__(15158);
4659
+ const error_utils_1 = __webpack_require__(36401);
4660
+ const types_1 = __webpack_require__(94820);
4661
+ const errors_1 = __webpack_require__(55191);
4662
+ const metrics_1 = __webpack_require__(32971);
4663
+ const utils_1 = __webpack_require__(2334);
4664
+ const constants_1 = __webpack_require__(64895);
4665
+ const file_utils_1 = __webpack_require__(52761);
4666
+ const debugLog = createDebugLogger('snyk-iac');
4667
+ async function downloadPolicyEngine(testConfig) {
4668
+ let downloadDurationSeconds = 0;
4669
+ const timer = new metrics_1.TimerMetricInstance('iac_policy_engine_download');
4670
+ timer.start();
4671
+ const dataBuffer = await fetch();
4672
+ assertValidChecksum(dataBuffer);
4673
+ const cachedPolicyEnginePath = await cache(dataBuffer, testConfig.iacCachePath);
4674
+ timer.stop();
4675
+ downloadDurationSeconds = Math.round(timer.getValue() / 1000);
4676
+ debugLog(`Downloaded and cached Policy Engine successfully in ${downloadDurationSeconds} seconds`);
4677
+ return cachedPolicyEnginePath;
4678
+ }
4679
+ exports.downloadPolicyEngine = downloadPolicyEngine;
4680
+ async function fetch() {
4681
+ debugLog(`Fetching Policy Engine executable from ${exports.policyEngineUrl}`);
4682
+ let policyEngineDataBuffer;
4667
4683
  try {
4668
- repoRoot = git_1.getRepositoryRoot() + '/';
4684
+ policyEngineDataBuffer = await utils_1.fetchCacheResource(exports.policyEngineUrl);
4669
4685
  }
4670
- catch {
4671
- repoRoot = path.join(process.cwd(), '/'); // the slash at the end is required, otherwise the artifactLocation.uri starts with a slash
4686
+ catch (err) {
4687
+ throw new FailedToDownloadPolicyEngineError();
4672
4688
  }
4673
- const tool = {
4674
- driver: {
4675
- name: 'Snyk IaC',
4676
- fullName: 'Snyk Infrastructure as Code',
4677
- version: version_1.getVersion(),
4678
- informationUri: 'https://docs.snyk.io/products/snyk-infrastructure-as-code',
4679
- rules: extractReportingDescriptor(scanResult.results),
4680
- },
4681
- };
4682
- return {
4683
- $schema: 'https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json',
4684
- version: '2.1.0',
4685
- runs: [
4686
- {
4687
- // https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317498
4688
- originalUriBaseIds: {
4689
- [PROJECT_ROOT_KEY]: {
4690
- uri: url_1.pathToFileURL(repoRoot).href,
4691
- description: {
4692
- text: 'The root directory for all project files.',
4693
- },
4694
- },
4695
- },
4696
- tool,
4697
- automationDetails: {
4698
- id: 'snyk-iac',
4699
- },
4700
- results: mapSnykIacTestResultsToSarifResults(scanResult.results),
4701
- },
4702
- ],
4703
- };
4689
+ debugLog('Policy Engine executable was fetched successfully');
4690
+ return policyEngineDataBuffer;
4704
4691
  }
4705
- exports.convertEngineToSarifResults = convertEngineToSarifResults;
4706
- function extractReportingDescriptor(results) {
4707
- const rules = {};
4708
- if (!(results === null || results === void 0 ? void 0 : results.vulnerabilities)) {
4709
- return Object.values(rules);
4692
+ exports.policyEngineUrl = `https://static.snyk.io/cli/iac/test/v${constants_1.policyEngineReleaseVersion}/${constants_1.policyEngineFileName}`;
4693
+ class FailedToDownloadPolicyEngineError extends errors_1.CustomError {
4694
+ constructor() {
4695
+ super(`Failed to download cache resource from ${exports.policyEngineUrl}`);
4696
+ this.code = types_1.IaCErrorCodes.FailedToDownloadPolicyEngineError;
4697
+ this.strCode = error_utils_1.getErrorStringCode(this.code);
4698
+ this.userMessage =
4699
+ `Could not fetch cache resource from: ${exports.policyEngineUrl}` +
4700
+ '\nEnsure valid network connection.';
4710
4701
  }
4711
- results.vulnerabilities.forEach((vulnerability) => {
4712
- if (rules[vulnerability.rule.id]) {
4713
- return;
4714
- }
4715
- const tags = ['security']; // switch to rules.labels once `snyk-iac-test` includes this info
4716
- rules[vulnerability.rule.id] = {
4717
- id: vulnerability.rule.id,
4718
- name: upperFirst(camelCase(vulnerability.rule.title)).replace(/ /g, ''),
4719
- shortDescription: {
4720
- text: `${upperFirst(vulnerability.severity)} severity - ${vulnerability.rule.title}`,
4721
- },
4722
- fullDescription: {
4723
- text: vulnerability.rule.description,
4724
- },
4725
- help: {
4726
- text: renderMarkdown(vulnerability.remediation),
4727
- markdown: vulnerability.remediation,
4728
- },
4729
- defaultConfiguration: {
4730
- level: sarif_output_1.getIssueLevel(vulnerability.severity),
4731
- },
4732
- properties: {
4733
- tags,
4734
- problem: {
4735
- severity: vulnerability.severity,
4736
- },
4737
- },
4738
- helpUri: vulnerability.rule.documentation,
4739
- };
4740
- });
4741
- return Object.values(rules);
4742
4702
  }
4743
- function renderMarkdown(markdown) {
4744
- const renderer = {
4745
- em(text) {
4746
- return text;
4747
- },
4748
- strong(text) {
4749
- return text;
4750
- },
4751
- link(text) {
4752
- return text;
4753
- },
4754
- blockquote(quote) {
4755
- return quote;
4756
- },
4757
- list(body) {
4758
- return body;
4759
- },
4760
- listitem(text) {
4761
- return text;
4762
- },
4763
- paragraph(text) {
4764
- return text;
4765
- },
4766
- codespan(text) {
4767
- return text;
4768
- },
4769
- code(code) {
4770
- return code;
4771
- },
4772
- heading(text) {
4773
- return `${text}\n`;
4774
- },
4775
- };
4776
- marked_1.marked.use({ renderer });
4777
- return marked_1.marked.parse(markdown);
4703
+ exports.FailedToDownloadPolicyEngineError = FailedToDownloadPolicyEngineError;
4704
+ function assertValidChecksum(dataBuffer) {
4705
+ const computedChecksum = crypto
4706
+ .createHash('sha256')
4707
+ .update(dataBuffer)
4708
+ .digest('hex');
4709
+ if (computedChecksum !== constants_1.policyEngineChecksum) {
4710
+ throw new FailedToDownloadPolicyEngineError();
4711
+ }
4712
+ debugLog('Fetched Policy Engine executable has valid checksum');
4778
4713
  }
4779
- function mapSnykIacTestResultsToSarifResults(results) {
4780
- const result = [];
4781
- if (!(results === null || results === void 0 ? void 0 : results.vulnerabilities)) {
4782
- return result;
4714
+ async function cache(dataBuffer, iacCachePath) {
4715
+ const savePath = pathLib.join(iacCachePath, constants_1.policyEngineFileName);
4716
+ debugLog(`Caching Policy Engine executable to ${savePath}`);
4717
+ try {
4718
+ await file_utils_1.saveFile(dataBuffer, savePath);
4783
4719
  }
4784
- results.vulnerabilities.forEach((vulnerability) => {
4785
- var _a;
4786
- result.push({
4787
- ruleId: vulnerability.rule.id,
4788
- message: {
4789
- text: `This line contains a potential ${vulnerability.severity} severity misconfiguration`,
4790
- },
4791
- locations: [
4792
- {
4793
- physicalLocation: {
4794
- artifactLocation: {
4795
- uri: vulnerability.resource.file,
4796
- uriBaseId: PROJECT_ROOT_KEY,
4797
- },
4798
- // We exclude the `region` key when the line number is missing or -1.
4799
- // https://docs.oasis-open.org/sarif/sarif/v2.0/csprd02/sarif-v2.0-csprd02.html#_Toc10127873
4800
- region: {
4801
- startLine: (_a = vulnerability.resource.line) !== null && _a !== void 0 ? _a : 1,
4802
- },
4803
- },
4804
- },
4805
- ],
4806
- });
4807
- });
4808
- return result;
4720
+ catch (err) {
4721
+ throw new FailedToCachePolicyEngineError(savePath);
4722
+ }
4723
+ debugLog(`Policy Engine executable was successfully cached`);
4724
+ return savePath;
4809
4725
  }
4726
+ class FailedToCachePolicyEngineError extends errors_1.CustomError {
4727
+ constructor(savePath) {
4728
+ super(`Failed to cache Policy Engine executable to ${savePath}`);
4729
+ this.code = types_1.IaCErrorCodes.FailedToCachePolicyEngineError;
4730
+ this.strCode = error_utils_1.getErrorStringCode(this.code);
4731
+ this.userMessage =
4732
+ `Could not write the downloaded cache resource to: ${savePath}` +
4733
+ '\nEnsure the cache directory is writable.';
4734
+ }
4735
+ }
4736
+ exports.FailedToCachePolicyEngineError = FailedToCachePolicyEngineError;
4810
4737
 
4811
4738
 
4812
4739
  /***/ }),
4813
4740
 
4814
- /***/ 50277:
4741
+ /***/ 90474:
4815
4742
  /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
4816
4743
 
4817
4744
  "use strict";
4818
4745
 
4819
- var _a;
4820
4746
  Object.defineProperty(exports, "__esModule", ({ value: true }));
4821
- exports.scan = exports.systemCachePath = void 0;
4822
- const childProcess = __webpack_require__(63129);
4823
- const errors_1 = __webpack_require__(55191);
4824
- const types_1 = __webpack_require__(94820);
4825
- const error_utils_1 = __webpack_require__(36401);
4826
- const newDebug = __webpack_require__(15158);
4827
- const results_1 = __webpack_require__(89752);
4828
- const os = __webpack_require__(12087);
4829
- const fs = __webpack_require__(35747);
4830
- const path = __webpack_require__(85622);
4831
- const rimraf = __webpack_require__(50984);
4832
- const config_1 = __webpack_require__(25425);
4833
- const api_token_1 = __webpack_require__(95181);
4834
- const analytics_1 = __webpack_require__(82744);
4835
- const env_paths_1 = __webpack_require__(21766);
4836
- const debug = newDebug('snyk-iac');
4837
- exports.systemCachePath = (_a = config_1.default.CACHE_PATH) !== null && _a !== void 0 ? _a : env_paths_1.default('snyk').cache;
4838
- function scan(options, policyEnginePath, rulesBundlePath) {
4839
- const configPath = createConfig(options);
4840
- try {
4841
- return scanWithConfig(options, policyEnginePath, rulesBundlePath, configPath);
4842
- }
4843
- finally {
4844
- deleteConfig(configPath);
4845
- }
4846
- }
4847
- exports.scan = scan;
4848
- function scanWithConfig(options, policyEnginePath, rulesBundlePath, configPath) {
4849
- const args = processFlags(options, rulesBundlePath, configPath);
4850
- args.push(...options.paths);
4851
- const process = childProcess.spawnSync(policyEnginePath, args, {
4852
- encoding: 'utf-8',
4853
- stdio: 'pipe',
4854
- maxBuffer: 1024 * 1024 * 10,
4855
- });
4856
- debug('policy engine standard error:\n%s', '\n' + process.stderr);
4857
- if (process.status && process.status !== 0) {
4858
- throw new ScanError(`invalid exit status: ${process.status}`);
4859
- }
4860
- if (process.error) {
4861
- throw new ScanError(`spawning process: ${process.error}`);
4862
- }
4863
- let snykIacTestOutput;
4864
- try {
4865
- snykIacTestOutput = JSON.parse(process.stdout);
4866
- }
4867
- catch (e) {
4868
- throw new ScanError(`invalid output encoding: ${e}`);
4869
- }
4870
- return results_1.mapSnykIacTestOutputToTestOutput(snykIacTestOutput);
4871
- }
4872
- function processFlags(options, rulesBundlePath, configPath) {
4873
- var _a, _b, _c;
4874
- const flags = [
4875
- '-cache-dir',
4876
- exports.systemCachePath,
4877
- '-bundle',
4878
- rulesBundlePath,
4879
- '-config',
4880
- configPath,
4881
- ];
4882
- if (options.severityThreshold) {
4883
- flags.push('-severity-threshold', options.severityThreshold);
4884
- }
4885
- if ((_a = options.attributes) === null || _a === void 0 ? void 0 : _a.criticality) {
4886
- flags.push('-project-business-criticality', options.attributes.criticality.join(','));
4887
- }
4888
- if ((_b = options.attributes) === null || _b === void 0 ? void 0 : _b.environment) {
4889
- flags.push('-project-environment', options.attributes.environment.join(','));
4890
- }
4891
- if ((_c = options.attributes) === null || _c === void 0 ? void 0 : _c.lifecycle) {
4892
- flags.push('-project-lifecycle', options.attributes.lifecycle.join(','));
4893
- }
4894
- if (options.projectTags) {
4895
- const stringifiedTags = options.projectTags
4896
- .map((tag) => {
4897
- return `${tag.key}=${tag.value}`;
4898
- })
4899
- .join(',');
4900
- flags.push('-project-tags', stringifiedTags);
4901
- }
4902
- if (options.report) {
4903
- flags.push('-report');
4904
- }
4905
- if (options.targetReference) {
4906
- flags.push('-target-reference', options.targetReference);
4907
- }
4908
- if (options.targetName) {
4909
- flags.push('-target-name', options.targetName);
4910
- }
4911
- if (options.remoteRepoUrl) {
4912
- flags.push('-remote-repo-url', options.remoteRepoUrl);
4913
- }
4914
- return flags;
4915
- }
4916
- function createConfig(options) {
4917
- try {
4918
- const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'snyk-'));
4919
- const tempConfig = path.join(tempDir, 'config.json');
4920
- const configData = JSON.stringify({
4921
- org: options.orgSettings.meta.org,
4922
- apiUrl: config_1.default.API,
4923
- apiAuth: api_token_1.getAuthHeader(),
4924
- allowAnalytics: analytics_1.allowAnalytics(),
4925
- policy: options.policy,
4926
- });
4927
- fs.writeFileSync(tempConfig, configData);
4928
- return tempConfig;
4929
- }
4930
- catch (e) {
4931
- throw new ScanError(`unable to create config file: ${e}`);
4932
- }
4933
- }
4934
- function deleteConfig(configPath) {
4935
- try {
4936
- rimraf.sync(path.dirname(configPath));
4937
- }
4938
- catch (e) {
4939
- debug('unable to delete temporary directory', e);
4940
- }
4941
- }
4942
- class ScanError extends errors_1.CustomError {
4943
- constructor(message) {
4944
- super(message);
4945
- this.code = types_1.IaCErrorCodes.PolicyEngineScanError;
4946
- this.strCode = error_utils_1.getErrorStringCode(this.code);
4947
- this.userMessage = 'An error occurred when running the scan';
4747
+ exports.initPolicyEngine = void 0;
4748
+ const createDebugLogger = __webpack_require__(15158);
4749
+ const lookup_local_1 = __webpack_require__(91387);
4750
+ const download_1 = __webpack_require__(58939);
4751
+ const debugLogger = createDebugLogger('snyk-iac');
4752
+ async function initPolicyEngine(testConfig) {
4753
+ debugLogger('Looking for Policy Engine locally');
4754
+ let policyEnginePath = await lookup_local_1.lookupLocalPolicyEngine(testConfig);
4755
+ if (!policyEnginePath) {
4756
+ debugLogger(`Downloading the Policy Engine and saving it at ${testConfig.iacCachePath}`);
4757
+ policyEnginePath = await download_1.downloadPolicyEngine(testConfig);
4948
4758
  }
4759
+ return policyEnginePath;
4949
4760
  }
4761
+ exports.initPolicyEngine = initPolicyEngine;
4950
4762
 
4951
4763
 
4952
4764
  /***/ }),
4953
4765
 
4954
- /***/ 89752:
4766
+ /***/ 91387:
4955
4767
  /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
4956
4768
 
4957
4769
  "use strict";
4958
4770
 
4959
4771
  Object.defineProperty(exports, "__esModule", ({ value: true }));
4960
- exports.mapSnykIacTestOutputToTestOutput = void 0;
4961
- const errors_1 = __webpack_require__(87198);
4962
- function mapSnykIacTestOutputToTestOutput(snykIacOutput) {
4963
- var _a;
4964
- const errors = (_a = snykIacOutput.errors) === null || _a === void 0 ? void 0 : _a.map((err) => new errors_1.SnykIacTestError(err));
4965
- const errWithoutPath = errors === null || errors === void 0 ? void 0 : errors.find((err) => { var _a; return !((_a = err.fields) === null || _a === void 0 ? void 0 : _a.path); });
4966
- if (errWithoutPath) {
4967
- throw errWithoutPath;
4772
+ exports.lookupLocalPolicyEngine = exports.InvalidUserPolicyEnginePathError = void 0;
4773
+ const file_utils_1 = __webpack_require__(52761);
4774
+ const errors_1 = __webpack_require__(55191);
4775
+ const types_1 = __webpack_require__(94820);
4776
+ const error_utils_1 = __webpack_require__(36401);
4777
+ const constants_1 = __webpack_require__(64895);
4778
+ const utils_1 = __webpack_require__(2334);
4779
+ class InvalidUserPolicyEnginePathError extends errors_1.CustomError {
4780
+ constructor(path, message, userMessage) {
4781
+ super(message ||
4782
+ 'Failed to find a valid Policy Engine executable in the configured path');
4783
+ this.code = types_1.IaCErrorCodes.InvalidUserPolicyEnginePathError;
4784
+ this.strCode = error_utils_1.getErrorStringCode(this.code);
4785
+ this.userMessage =
4786
+ userMessage ||
4787
+ `Could not find a valid Policy Engine executable in the configured path: ${path}` +
4788
+ '\nEnsure the configured path points to a valid Policy Engine executable.';
4968
4789
  }
4969
- return {
4970
- results: snykIacOutput.results,
4971
- errors,
4790
+ }
4791
+ exports.InvalidUserPolicyEnginePathError = InvalidUserPolicyEnginePathError;
4792
+ async function lookupLocalPolicyEngine(testConfig) {
4793
+ const validPolicyEngineCondition = async (path) => {
4794
+ return await file_utils_1.isExe(path);
4972
4795
  };
4796
+ try {
4797
+ return await utils_1.lookupLocal(testConfig.iacCachePath, constants_1.policyEngineFileName, testConfig.userPolicyEnginePath, validPolicyEngineCondition);
4798
+ }
4799
+ catch (err) {
4800
+ if (err instanceof utils_1.InvalidUserPathError) {
4801
+ throw new InvalidUserPolicyEnginePathError(testConfig.userPolicyEnginePath);
4802
+ }
4803
+ else {
4804
+ throw err;
4805
+ }
4806
+ }
4973
4807
  }
4974
- exports.mapSnykIacTestOutputToTestOutput = mapSnykIacTestOutputToTestOutput;
4808
+ exports.lookupLocalPolicyEngine = lookupLocalPolicyEngine;
4975
4809
 
4976
4810
 
4977
4811
  /***/ }),
4978
4812
 
4979
- /***/ 88929:
4980
- /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
4813
+ /***/ 75957:
4814
+ /***/ ((__unused_webpack_module, exports) => {
4981
4815
 
4982
4816
  "use strict";
4983
4817
 
4984
4818
  Object.defineProperty(exports, "__esModule", ({ value: true }));
4985
- exports.setup = void 0;
4986
- const local_cache_1 = __webpack_require__(14379);
4987
- async function setup(testConfig) {
4988
- return await local_cache_1.initLocalCache(testConfig);
4989
- }
4990
- exports.setup = setup;
4819
+ exports.rulesBundleName = void 0;
4820
+ exports.rulesBundleName = 'bundle-experimental.tar.gz';
4991
4821
 
4992
4822
 
4993
4823
  /***/ }),
4994
4824
 
4995
- /***/ 14379:
4825
+ /***/ 30313:
4996
4826
  /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
4997
4827
 
4998
4828
  "use strict";
4999
4829
 
5000
4830
  Object.defineProperty(exports, "__esModule", ({ value: true }));
5001
- exports.initLocalCache = void 0;
5002
- const rules_bundle_1 = __webpack_require__(82373);
5003
- const policy_engine_1 = __webpack_require__(41135);
5004
- const file_utils_1 = __webpack_require__(52761);
4831
+ exports.FailedToCacheRulesBundleError = exports.FailedToDownloadRulesBundleError = exports.rulesBundleUrl = exports.downloadRulesBundle = void 0;
4832
+ const createDebugLogger = __webpack_require__(15158);
4833
+ const path = __webpack_require__(85622);
4834
+ const error_utils_1 = __webpack_require__(36401);
4835
+ const types_1 = __webpack_require__(94820);
5005
4836
  const errors_1 = __webpack_require__(55191);
5006
- const local_cache_1 = __webpack_require__(50089);
5007
- async function initLocalCache(testConfig) {
4837
+ const metrics_1 = __webpack_require__(32971);
4838
+ const file_utils_1 = __webpack_require__(52761);
4839
+ const utils_1 = __webpack_require__(2334);
4840
+ const constants_1 = __webpack_require__(75957);
4841
+ const debugLog = createDebugLogger('snyk-iac');
4842
+ async function downloadRulesBundle(testConfig) {
4843
+ let downloadDurationSeconds = 0;
4844
+ const timer = new metrics_1.TimerMetricInstance('iac_rules_bundle_download');
4845
+ timer.start();
4846
+ const dataBuffer = await fetch();
4847
+ const cachedRulesBundlePath = await cache(dataBuffer, testConfig.iacCachePath);
4848
+ timer.stop();
4849
+ downloadDurationSeconds = Math.round(timer.getValue() / 1000);
4850
+ debugLog(`Downloaded and cached rules bundle successfully in ${downloadDurationSeconds} seconds`);
4851
+ return cachedRulesBundlePath;
4852
+ }
4853
+ exports.downloadRulesBundle = downloadRulesBundle;
4854
+ async function fetch() {
4855
+ debugLog(`Fetching rules bundle from ${exports.rulesBundleUrl}`);
4856
+ let rulesBundleDataBuffer;
5008
4857
  try {
5009
- await file_utils_1.createDirIfNotExists(testConfig.iacCachePath);
5010
- const policyEnginePath = await policy_engine_1.initPolicyEngine(testConfig);
5011
- const rulesBundlePath = await rules_bundle_1.initRulesBundle(testConfig);
5012
- return { policyEnginePath, rulesBundlePath };
4858
+ rulesBundleDataBuffer = await utils_1.fetchCacheResource(exports.rulesBundleUrl);
5013
4859
  }
5014
4860
  catch (err) {
5015
- throw err instanceof errors_1.CustomError ? err : new local_cache_1.FailedToInitLocalCacheError();
4861
+ throw new FailedToDownloadRulesBundleError();
5016
4862
  }
4863
+ debugLog('Rules bundle was fetched successfully');
4864
+ return rulesBundleDataBuffer;
5017
4865
  }
5018
- exports.initLocalCache = initLocalCache;
4866
+ exports.rulesBundleUrl = 'https://static.snyk.io/cli/wasm/bundle-experimental.tar.gz';
4867
+ class FailedToDownloadRulesBundleError extends errors_1.CustomError {
4868
+ constructor() {
4869
+ super(`Failed to download cache resource from ${exports.rulesBundleUrl}`);
4870
+ this.code = types_1.IaCErrorCodes.FailedToDownloadRulesBundleError;
4871
+ this.strCode = error_utils_1.getErrorStringCode(this.code);
4872
+ this.userMessage =
4873
+ `Could not fetch cache resource from: ${exports.rulesBundleUrl}` +
4874
+ '\nEnsure valid network connection.';
4875
+ }
4876
+ }
4877
+ exports.FailedToDownloadRulesBundleError = FailedToDownloadRulesBundleError;
4878
+ async function cache(dataBuffer, iacCachePath) {
4879
+ const savePath = path.join(iacCachePath, constants_1.rulesBundleName);
4880
+ debugLog(`Caching rules bundle to ${savePath}`);
4881
+ try {
4882
+ await file_utils_1.saveFile(dataBuffer, savePath);
4883
+ }
4884
+ catch (err) {
4885
+ throw new FailedToCacheRulesBundleError(savePath);
4886
+ }
4887
+ debugLog(`Rules bundle was successfully cached`);
4888
+ return savePath;
4889
+ }
4890
+ class FailedToCacheRulesBundleError extends errors_1.CustomError {
4891
+ constructor(savePath) {
4892
+ super(`Failed to cache rules bundle to ${savePath}`);
4893
+ this.code = types_1.IaCErrorCodes.FailedToCacheRulesBundleError;
4894
+ this.strCode = error_utils_1.getErrorStringCode(this.code);
4895
+ this.userMessage =
4896
+ `Could not write the downloaded cache resource to: ${savePath}` +
4897
+ '\nEnsure the cache directory is writable.';
4898
+ }
4899
+ }
4900
+ exports.FailedToCacheRulesBundleError = FailedToCacheRulesBundleError;
5019
4901
 
5020
4902
 
5021
4903
  /***/ }),
5022
4904
 
5023
- /***/ 89574:
4905
+ /***/ 51897:
5024
4906
  /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
5025
4907
 
5026
- "use strict";
5027
-
5028
- Object.defineProperty(exports, "__esModule", ({ value: true }));
5029
- exports.policyEngineChecksum = exports.policyEngineFileName = exports.policyEngineReleaseVersion = void 0;
5030
- const utils_1 = __webpack_require__(92040);
5031
- /**
5032
- * The Policy Engine release version associated with this Snyk CLI version.
5033
- */
5034
- exports.policyEngineReleaseVersion = utils_1.policyEngineVersion;
5035
- /**
5036
- * The Policy Engine executable's file name.
5037
- */
5038
- exports.policyEngineFileName = utils_1.formatPolicyEngineFileName(exports.policyEngineReleaseVersion);
5039
- exports.policyEngineChecksum = utils_1.getChecksum(exports.policyEngineFileName);
5040
-
4908
+ "use strict";
4909
+
4910
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
4911
+ exports.initRulesBundle = void 0;
4912
+ const createDebugLogger = __webpack_require__(15158);
4913
+ const download_1 = __webpack_require__(30313);
4914
+ const debugLogger = createDebugLogger('snyk-iac');
4915
+ async function initRulesBundle(testConfig) {
4916
+ // We are currently using the legacy rules bundle and we need to re-download it each time to use the latest one available.
4917
+ // debugLogger('Looking for rules bundle locally');
4918
+ // let rulesBundlePath = await lookupLocalRulesBundle(testConfig);
4919
+ debugLogger(`Downloading the rules bundle and saving it at ${testConfig.iacCachePath}`);
4920
+ return await download_1.downloadRulesBundle(testConfig);
4921
+ }
4922
+ exports.initRulesBundle = initRulesBundle;
4923
+
5041
4924
 
5042
4925
  /***/ }),
5043
4926
 
5044
- /***/ 92040:
4927
+ /***/ 2334:
5045
4928
  /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
5046
4929
 
5047
4930
  "use strict";
5048
4931
 
5049
4932
  Object.defineProperty(exports, "__esModule", ({ value: true }));
5050
- exports.getChecksum = exports.formatPolicyEngineFileName = exports.policyEngineVersion = void 0;
5051
- const os = __webpack_require__(12087);
5052
- const policyEngineChecksums = `0313de2afa00ed6301e8cadbe344e448085c6e94cb0e87a06264b908c3c5e2de snyk-iac-test_0.22.0_Windows_x86_64.exe
5053
- 031416e2714ba2bfe85bb294f588eebc20b028dae2222b1929df2072fd01028d snyk-iac-test_0.22.0_Windows_arm64.exe
5054
- 03dcc3b16f1d84f80346aaf05fe7f8a5f8099af765c9979e8f36ee4b9cee4fb3 snyk-iac-test_0.22.0_Darwin_x86_64
5055
- 54d0a20a209c45f948f147e4280650b366b4f8252b042fe4a30bec832fe3f915 snyk-iac-test_0.22.0_Darwin_arm64
5056
- cb0d714746310cda42914163572e39c4e4f044342d54695ac901d80e03c9ecf8 snyk-iac-test_0.22.0_Linux_x86_64
5057
- f95568949342bf7f33285500022a9ee0f3d64fc6dd601f16ce9b654e43cb6de6 snyk-iac-test_0.22.0_Linux_arm64
5058
- `;
5059
- exports.policyEngineVersion = getPolicyEngineVersion();
5060
- function formatPolicyEngineFileName(releaseVersion) {
5061
- let platform = 'Linux';
5062
- switch (os.platform()) {
5063
- case 'darwin':
5064
- platform = 'Darwin';
5065
- break;
5066
- case 'win32':
5067
- platform = 'Windows';
5068
- break;
5069
- }
5070
- const arch = os.arch() === 'arm64' ? 'arm64' : 'x86_64';
5071
- const execExt = os.platform() === 'win32' ? '.exe' : '';
5072
- return `snyk-iac-test_${releaseVersion}_${platform}_${arch}${execExt}`;
5073
- }
5074
- exports.formatPolicyEngineFileName = formatPolicyEngineFileName;
5075
- function getChecksum(policyEngineFileName) {
5076
- const lines = policyEngineChecksums.split(/\r?\n/);
5077
- const checksumsMap = new Map();
5078
- for (const line of lines) {
5079
- const [checksum, file] = line.split(/\s+/);
5080
- if (file && checksum) {
5081
- checksumsMap.set(file, checksum.trim());
4933
+ exports.fetchCacheResource = exports.InvalidUserPathError = exports.lookupLocal = void 0;
4934
+ const createDebugLogger = __webpack_require__(15158);
4935
+ const path = __webpack_require__(85622);
4936
+ const errors_1 = __webpack_require__(55191);
4937
+ const request_1 = __webpack_require__(52050);
4938
+ const debugLogger = createDebugLogger('snyk-iac');
4939
+ async function lookupLocal(iacCachePath, resourceName, userResourcePath, validResourceCondition) {
4940
+ // Lookup in custom path.
4941
+ if (userResourcePath) {
4942
+ debugLogger('User configured path detected: %s', userResourcePath);
4943
+ if (await validResourceCondition(userResourcePath)) {
4944
+ return userResourcePath;
4945
+ }
4946
+ else {
4947
+ // When using this function please catch this Error and throw a new specific Custom Error.
4948
+ throw new InvalidUserPathError(`Failed to find a valid resource in the configured path: ${userResourcePath}`);
5082
4949
  }
5083
4950
  }
5084
- const policyEngineChecksum = checksumsMap.get(policyEngineFileName);
5085
- if (!policyEngineChecksum) {
5086
- // This is an internal error and technically it should never be thrown
5087
- throw new Error(`Could not find checksum for ${policyEngineFileName}`);
4951
+ // Lookup in cache.
4952
+ else {
4953
+ const cachedResourcePath = path.join(iacCachePath, resourceName);
4954
+ if (await validResourceCondition(cachedResourcePath)) {
4955
+ return cachedResourcePath;
4956
+ }
5088
4957
  }
5089
- return policyEngineChecksum;
5090
4958
  }
5091
- exports.getChecksum = getChecksum;
5092
- function getPolicyEngineVersion() {
5093
- const lines = policyEngineChecksums.split(/\r?\n/);
5094
- if (lines.length == 0) {
5095
- throw new Error('empty checksum');
5096
- }
5097
- const line = lines.find((line) => line.length > 0);
5098
- if (line === undefined) {
5099
- throw new Error('empty checksum lines');
5100
- }
5101
- const parts = line.split(/\s+/);
5102
- if (parts.length < 2) {
5103
- throw new Error('invalid checksum line');
4959
+ exports.lookupLocal = lookupLocal;
4960
+ class InvalidUserPathError extends errors_1.CustomError {
4961
+ constructor(message) {
4962
+ super(message);
5104
4963
  }
5105
- const components = parts[1].split('_');
5106
- if (components.length < 2) {
5107
- throw new Error('invalid checksum file name');
4964
+ }
4965
+ exports.InvalidUserPathError = InvalidUserPathError;
4966
+ async function fetchCacheResource(url) {
4967
+ const { res, body: cacheResourceBuffer } = await request_1.makeRequest({
4968
+ url,
4969
+ });
4970
+ if (res.statusCode !== 200) {
4971
+ throw new errors_1.CustomError(`Failed to download cache resource from ${url}`);
5108
4972
  }
5109
- return components[1];
4973
+ return cacheResourceBuffer;
5110
4974
  }
4975
+ exports.fetchCacheResource = fetchCacheResource;
5111
4976
 
5112
4977
 
5113
4978
  /***/ }),
5114
4979
 
5115
- /***/ 18739:
4980
+ /***/ 99687:
5116
4981
  /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
5117
4982
 
5118
4983
  "use strict";
5119
4984
 
5120
4985
  Object.defineProperty(exports, "__esModule", ({ value: true }));
5121
- exports.FailedToCachePolicyEngineError = exports.FailedToDownloadPolicyEngineError = exports.policyEngineUrl = exports.downloadPolicyEngine = void 0;
5122
- const pathLib = __webpack_require__(85622);
5123
- const crypto = __webpack_require__(76417);
5124
- const createDebugLogger = __webpack_require__(15158);
5125
- const error_utils_1 = __webpack_require__(36401);
5126
- const types_1 = __webpack_require__(94820);
4986
+ exports.FoundIssuesError = exports.NoLoadableInputError = exports.NoSuccessfulScansError = exports.buildOutput = void 0;
4987
+ const os_1 = __webpack_require__(12087);
4988
+ const json_1 = __webpack_require__(71909);
4989
+ const types_1 = __webpack_require__(55246);
4990
+ const text_1 = __webpack_require__(86166);
4991
+ const json_2 = __webpack_require__(27019);
4992
+ const types_2 = __webpack_require__(94820);
4993
+ const sarif_1 = __webpack_require__(87999);
5127
4994
  const errors_1 = __webpack_require__(55191);
5128
- const metrics_1 = __webpack_require__(32971);
5129
- const utils_1 = __webpack_require__(42256);
5130
- const constants_1 = __webpack_require__(89574);
5131
- const file_utils_1 = __webpack_require__(52761);
5132
- const debugLog = createDebugLogger('snyk-iac');
5133
- async function downloadPolicyEngine(testConfig) {
5134
- let downloadDurationSeconds = 0;
5135
- const timer = new metrics_1.TimerMetricInstance('iac_policy_engine_download');
5136
- timer.start();
5137
- const dataBuffer = await fetch();
5138
- assertValidChecksum(dataBuffer);
5139
- const cachedPolicyEnginePath = await cache(dataBuffer, testConfig.iacCachePath);
5140
- timer.stop();
5141
- downloadDurationSeconds = Math.round(timer.getValue() / 1000);
5142
- debugLog(`Downloaded and cached Policy Engine successfully in ${downloadDurationSeconds} seconds`);
5143
- return cachedPolicyEnginePath;
4995
+ const strip_ansi_1 = __webpack_require__(76003);
4996
+ const path = __webpack_require__(85622);
4997
+ const error_utils_1 = __webpack_require__(36401);
4998
+ const output_1 = __webpack_require__(39313);
4999
+ function buildOutput({ scanResult, testSpinner, orgSettings, options, }) {
5000
+ if (scanResult.results) {
5001
+ testSpinner === null || testSpinner === void 0 ? void 0 : testSpinner.succeed(text_1.spinnerSuccessMessage);
5002
+ }
5003
+ else {
5004
+ testSpinner === null || testSpinner === void 0 ? void 0 : testSpinner.stop();
5005
+ }
5006
+ const { responseData, jsonData, sarifData } = buildTestCommandResultData({
5007
+ scanResult,
5008
+ orgSettings,
5009
+ options,
5010
+ });
5011
+ if (options.json || options.sarif) {
5012
+ return types_1.TestCommandResult.createJsonTestCommandResult(responseData, jsonData, sarifData);
5013
+ }
5014
+ return types_1.TestCommandResult.createHumanReadableTestCommandResult(responseData, jsonData, sarifData);
5144
5015
  }
5145
- exports.downloadPolicyEngine = downloadPolicyEngine;
5146
- async function fetch() {
5147
- debugLog(`Fetching Policy Engine executable from ${exports.policyEngineUrl}`);
5148
- let policyEngineDataBuffer;
5149
- try {
5150
- policyEngineDataBuffer = await utils_1.fetchCacheResource(exports.policyEngineUrl);
5016
+ exports.buildOutput = buildOutput;
5017
+ function buildTestCommandResultData({ scanResult, orgSettings, options, }) {
5018
+ var _a, _b, _c, _d, _e;
5019
+ const projectName = (_c = (_b = (_a = scanResult.results) === null || _a === void 0 ? void 0 : _a.metadata) === null || _b === void 0 ? void 0 : _b.projectName) !== null && _c !== void 0 ? _c : path.basename(process.cwd());
5020
+ const jsonData = json_2.jsonStringifyLargeObject(json_1.convertEngineToJsonResults({
5021
+ results: scanResult,
5022
+ projectName,
5023
+ orgSettings,
5024
+ }));
5025
+ const sarifData = json_2.jsonStringifyLargeObject(sarif_1.convertEngineToSarifResults(scanResult));
5026
+ assertHasSuccessfulScans(scanResult, { json: jsonData, sarif: sarifData }, options);
5027
+ let responseData;
5028
+ if (options.json) {
5029
+ responseData = jsonData;
5151
5030
  }
5152
- catch (err) {
5153
- throw new FailedToDownloadPolicyEngineError();
5031
+ else if (options.sarif) {
5032
+ responseData = sarifData;
5154
5033
  }
5155
- debugLog('Policy Engine executable was fetched successfully');
5156
- return policyEngineDataBuffer;
5034
+ else {
5035
+ responseData = buildTextOutput({
5036
+ scanResult,
5037
+ projectName,
5038
+ orgSettings,
5039
+ options,
5040
+ });
5041
+ }
5042
+ const hasVulnerabilities = !!((_e = (_d = scanResult.results) === null || _d === void 0 ? void 0 : _d.vulnerabilities) === null || _e === void 0 ? void 0 : _e.length);
5043
+ if (hasVulnerabilities) {
5044
+ throw new FoundIssuesError({
5045
+ response: responseData,
5046
+ json: jsonData,
5047
+ sarif: sarifData,
5048
+ });
5049
+ }
5050
+ return { responseData, jsonData, sarifData };
5157
5051
  }
5158
- exports.policyEngineUrl = `https://static.snyk.io/cli/iac/test/v${constants_1.policyEngineReleaseVersion}/${constants_1.policyEngineFileName}`;
5159
- class FailedToDownloadPolicyEngineError extends errors_1.CustomError {
5160
- constructor() {
5161
- super(`Failed to download cache resource from ${exports.policyEngineUrl}`);
5162
- this.code = types_1.IaCErrorCodes.FailedToDownloadPolicyEngineError;
5163
- this.strCode = error_utils_1.getErrorStringCode(this.code);
5164
- this.userMessage =
5165
- `Could not fetch cache resource from: ${exports.policyEngineUrl}` +
5166
- '\nEnsure valid network connection.';
5052
+ const SEPARATOR = '\n-------------------------------------------------------\n';
5053
+ function buildTextOutput({ scanResult, projectName, orgSettings, options, }) {
5054
+ let response = '';
5055
+ const testData = text_1.formatSnykIacTestTestData(scanResult.results, projectName, orgSettings.meta.org);
5056
+ response +=
5057
+ os_1.EOL +
5058
+ text_1.getIacDisplayedIssues(testData.resultsBySeverity, {
5059
+ shouldShowLineNumbers: true,
5060
+ });
5061
+ if (scanResult.errors) {
5062
+ const testFailures = scanResult.errors.map((error) => ({
5063
+ filePath: error.fields.path,
5064
+ failureReason: error.userMessage,
5065
+ }));
5066
+ response += os_1.EOL.repeat(2) + text_1.formatIacTestFailures(testFailures);
5067
+ }
5068
+ response += os_1.EOL;
5069
+ response += SEPARATOR;
5070
+ response += os_1.EOL;
5071
+ response += text_1.formatIacTestSummary(testData);
5072
+ response += os_1.EOL;
5073
+ if (options.report) {
5074
+ response += output_1.buildShareResultsSummary({
5075
+ orgName: orgSettings.meta.org,
5076
+ projectName,
5077
+ options,
5078
+ isIacCustomRulesEntitlementEnabled: false,
5079
+ isIacShareCliResultsCustomRulesSupported: false,
5080
+ });
5081
+ response += os_1.EOL;
5167
5082
  }
5083
+ if (output_1.shouldPrintShareResultsTip(options)) {
5084
+ response += SEPARATOR + os_1.EOL + text_1.shareResultsTip + os_1.EOL;
5085
+ }
5086
+ return response;
5168
5087
  }
5169
- exports.FailedToDownloadPolicyEngineError = FailedToDownloadPolicyEngineError;
5170
- function assertValidChecksum(dataBuffer) {
5171
- const computedChecksum = crypto
5172
- .createHash('sha256')
5173
- .update(dataBuffer)
5174
- .digest('hex');
5175
- if (computedChecksum !== constants_1.policyEngineChecksum) {
5176
- throw new FailedToDownloadPolicyEngineError();
5088
+ function assertHasSuccessfulScans(scanResult, responseData, options) {
5089
+ var _a, _b, _c;
5090
+ const hasResources = !!((_b = (_a = scanResult.results) === null || _a === void 0 ? void 0 : _a.resources) === null || _b === void 0 ? void 0 : _b.length);
5091
+ const hasErrors = !!((_c = scanResult.errors) === null || _c === void 0 ? void 0 : _c.length);
5092
+ const hasSuccessfulScans = hasResources || !hasErrors;
5093
+ if (!hasSuccessfulScans) {
5094
+ const hasLoadableInput = scanResult.errors.some((error) => error.code !== types_2.IaCErrorCodes.NoLoadableInput);
5095
+ throw hasLoadableInput
5096
+ ? new NoSuccessfulScansError(responseData, scanResult.errors, options)
5097
+ : new NoLoadableInputError(responseData, scanResult.errors, options);
5098
+ }
5099
+ }
5100
+ class NoSuccessfulScansError extends errors_1.FormattedCustomError {
5101
+ constructor(responseData, errors, options) {
5102
+ const firstErr = errors[0];
5103
+ const isText = !options.json && !options.sarif;
5104
+ const message = options.json
5105
+ ? responseData.json
5106
+ : options.sarif
5107
+ ? responseData.sarif
5108
+ : firstErr.message;
5109
+ super(message, isText
5110
+ ? text_1.formatIacTestFailures(errors.map((scanError) => ({
5111
+ failureReason: scanError.userMessage,
5112
+ filePath: scanError.fields.path,
5113
+ })))
5114
+ : strip_ansi_1.default(message));
5115
+ this.code = firstErr.code;
5116
+ this.strCode = firstErr.strCode;
5117
+ this.json = isText ? responseData.json : message;
5118
+ this.jsonStringifiedResults = responseData.json;
5119
+ this.sarifStringifiedResults = responseData.sarif;
5120
+ this.fields = firstErr.fields;
5177
5121
  }
5178
- debugLog('Fetched Policy Engine executable has valid checksum');
5179
- }
5180
- async function cache(dataBuffer, iacCachePath) {
5181
- const savePath = pathLib.join(iacCachePath, constants_1.policyEngineFileName);
5182
- debugLog(`Caching Policy Engine executable to ${savePath}`);
5183
- try {
5184
- await file_utils_1.saveFile(dataBuffer, savePath);
5122
+ get path() {
5123
+ var _a;
5124
+ return (_a = this.fields) === null || _a === void 0 ? void 0 : _a.path;
5185
5125
  }
5186
- catch (err) {
5187
- throw new FailedToCachePolicyEngineError(savePath);
5126
+ set path(path1) {
5127
+ this.fields.path = path1;
5188
5128
  }
5189
- debugLog(`Policy Engine executable was successfully cached`);
5190
- return savePath;
5191
5129
  }
5192
- class FailedToCachePolicyEngineError extends errors_1.CustomError {
5193
- constructor(savePath) {
5194
- super(`Failed to cache Policy Engine executable to ${savePath}`);
5195
- this.code = types_1.IaCErrorCodes.FailedToCachePolicyEngineError;
5196
- this.strCode = error_utils_1.getErrorStringCode(this.code);
5197
- this.userMessage =
5198
- `Could not write the downloaded cache resource to: ${savePath}` +
5199
- '\nEnsure the cache directory is writable.';
5130
+ exports.NoSuccessfulScansError = NoSuccessfulScansError;
5131
+ class NoLoadableInputError extends NoSuccessfulScansError {
5132
+ constructor(responseData, errors, options) {
5133
+ super(responseData, errors, options);
5134
+ (this.code = types_2.IaCErrorCodes.NoFilesToScanError),
5135
+ (this.strCode = error_utils_1.getErrorStringCode(this.code));
5200
5136
  }
5201
5137
  }
5202
- exports.FailedToCachePolicyEngineError = FailedToCachePolicyEngineError;
5203
-
5204
-
5205
- /***/ }),
5206
-
5207
- /***/ 41135:
5208
- /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
5209
-
5210
- "use strict";
5211
-
5212
- Object.defineProperty(exports, "__esModule", ({ value: true }));
5213
- exports.initPolicyEngine = void 0;
5214
- const createDebugLogger = __webpack_require__(15158);
5215
- const lookup_local_1 = __webpack_require__(73164);
5216
- const download_1 = __webpack_require__(18739);
5217
- const debugLogger = createDebugLogger('snyk-iac');
5218
- async function initPolicyEngine(testConfig) {
5219
- debugLogger('Looking for Policy Engine locally');
5220
- let policyEnginePath = await lookup_local_1.lookupLocalPolicyEngine(testConfig);
5221
- if (!policyEnginePath) {
5222
- debugLogger(`Downloading the Policy Engine and saving it at ${testConfig.iacCachePath}`);
5223
- policyEnginePath = await download_1.downloadPolicyEngine(testConfig);
5138
+ exports.NoLoadableInputError = NoLoadableInputError;
5139
+ class FoundIssuesError extends errors_1.CustomError {
5140
+ constructor(responseData) {
5141
+ super(responseData.response);
5142
+ this.code = 'VULNS';
5143
+ this.strCode = 'VULNS';
5144
+ this.userMessage = responseData.response;
5145
+ this.jsonStringifiedResults = responseData.json;
5146
+ this.sarifStringifiedResults = responseData.sarif;
5224
5147
  }
5225
- return policyEnginePath;
5226
5148
  }
5227
- exports.initPolicyEngine = initPolicyEngine;
5149
+ exports.FoundIssuesError = FoundIssuesError;
5228
5150
 
5229
5151
 
5230
5152
  /***/ }),
5231
5153
 
5232
- /***/ 73164:
5154
+ /***/ 87999:
5233
5155
  /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
5234
5156
 
5235
5157
  "use strict";
5236
5158
 
5237
5159
  Object.defineProperty(exports, "__esModule", ({ value: true }));
5238
- exports.lookupLocalPolicyEngine = exports.InvalidUserPolicyEnginePathError = void 0;
5239
- const file_utils_1 = __webpack_require__(52761);
5240
- const errors_1 = __webpack_require__(55191);
5241
- const types_1 = __webpack_require__(94820);
5242
- const error_utils_1 = __webpack_require__(36401);
5243
- const constants_1 = __webpack_require__(89574);
5244
- const utils_1 = __webpack_require__(42256);
5245
- class InvalidUserPolicyEnginePathError extends errors_1.CustomError {
5246
- constructor(path, message, userMessage) {
5247
- super(message ||
5248
- 'Failed to find a valid Policy Engine executable in the configured path');
5249
- this.code = types_1.IaCErrorCodes.InvalidUserPolicyEnginePathError;
5250
- this.strCode = error_utils_1.getErrorStringCode(this.code);
5251
- this.userMessage =
5252
- userMessage ||
5253
- `Could not find a valid Policy Engine executable in the configured path: ${path}` +
5254
- '\nEnsure the configured path points to a valid Policy Engine executable.';
5160
+ exports.convertEngineToSarifResults = void 0;
5161
+ const url_1 = __webpack_require__(78835);
5162
+ const marked_1 = __webpack_require__(30970);
5163
+ const path = __webpack_require__(85622);
5164
+ const upperFirst = __webpack_require__(90039);
5165
+ const camelCase = __webpack_require__(76884);
5166
+ const version_1 = __webpack_require__(38217);
5167
+ const sarif_output_1 = __webpack_require__(5034);
5168
+ const git_1 = __webpack_require__(82421);
5169
+ // Used to reference the base path in results.
5170
+ const PROJECT_ROOT_KEY = 'PROJECTROOT';
5171
+ function convertEngineToSarifResults(scanResult) {
5172
+ let repoRoot;
5173
+ try {
5174
+ repoRoot = git_1.getRepositoryRoot() + '/';
5255
5175
  }
5256
- }
5257
- exports.InvalidUserPolicyEnginePathError = InvalidUserPolicyEnginePathError;
5258
- async function lookupLocalPolicyEngine(testConfig) {
5259
- const validPolicyEngineCondition = async (path) => {
5260
- return await file_utils_1.isExe(path);
5176
+ catch {
5177
+ repoRoot = path.join(process.cwd(), '/'); // the slash at the end is required, otherwise the artifactLocation.uri starts with a slash
5178
+ }
5179
+ const tool = {
5180
+ driver: {
5181
+ name: 'Snyk IaC',
5182
+ fullName: 'Snyk Infrastructure as Code',
5183
+ version: version_1.getVersion(),
5184
+ informationUri: 'https://docs.snyk.io/products/snyk-infrastructure-as-code',
5185
+ rules: extractReportingDescriptor(scanResult.results),
5186
+ },
5261
5187
  };
5262
- try {
5263
- return await utils_1.lookupLocal(testConfig.iacCachePath, constants_1.policyEngineFileName, testConfig.userPolicyEnginePath, validPolicyEngineCondition);
5188
+ return {
5189
+ $schema: 'https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json',
5190
+ version: '2.1.0',
5191
+ runs: [
5192
+ {
5193
+ // https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317498
5194
+ originalUriBaseIds: {
5195
+ [PROJECT_ROOT_KEY]: {
5196
+ uri: url_1.pathToFileURL(repoRoot).href,
5197
+ description: {
5198
+ text: 'The root directory for all project files.',
5199
+ },
5200
+ },
5201
+ },
5202
+ tool,
5203
+ automationDetails: {
5204
+ id: 'snyk-iac',
5205
+ },
5206
+ results: mapSnykIacTestResultsToSarifResults(scanResult.results),
5207
+ },
5208
+ ],
5209
+ };
5210
+ }
5211
+ exports.convertEngineToSarifResults = convertEngineToSarifResults;
5212
+ function extractReportingDescriptor(results) {
5213
+ const rules = {};
5214
+ if (!(results === null || results === void 0 ? void 0 : results.vulnerabilities)) {
5215
+ return Object.values(rules);
5264
5216
  }
5265
- catch (err) {
5266
- if (err instanceof utils_1.InvalidUserPathError) {
5267
- throw new InvalidUserPolicyEnginePathError(testConfig.userPolicyEnginePath);
5268
- }
5269
- else {
5270
- throw err;
5217
+ results.vulnerabilities.forEach((vulnerability) => {
5218
+ if (rules[vulnerability.rule.id]) {
5219
+ return;
5271
5220
  }
5221
+ const tags = ['security']; // switch to rules.labels once `snyk-iac-test` includes this info
5222
+ rules[vulnerability.rule.id] = {
5223
+ id: vulnerability.rule.id,
5224
+ name: upperFirst(camelCase(vulnerability.rule.title)).replace(/ /g, ''),
5225
+ shortDescription: {
5226
+ text: `${upperFirst(vulnerability.severity)} severity - ${vulnerability.rule.title}`,
5227
+ },
5228
+ fullDescription: {
5229
+ text: vulnerability.rule.description,
5230
+ },
5231
+ help: {
5232
+ text: renderMarkdown(vulnerability.remediation),
5233
+ markdown: vulnerability.remediation,
5234
+ },
5235
+ defaultConfiguration: {
5236
+ level: sarif_output_1.getIssueLevel(vulnerability.severity),
5237
+ },
5238
+ properties: {
5239
+ tags,
5240
+ problem: {
5241
+ severity: vulnerability.severity,
5242
+ },
5243
+ },
5244
+ helpUri: vulnerability.rule.documentation,
5245
+ };
5246
+ });
5247
+ return Object.values(rules);
5248
+ }
5249
+ function renderMarkdown(markdown) {
5250
+ const renderer = {
5251
+ em(text) {
5252
+ return text;
5253
+ },
5254
+ strong(text) {
5255
+ return text;
5256
+ },
5257
+ link(text) {
5258
+ return text;
5259
+ },
5260
+ blockquote(quote) {
5261
+ return quote;
5262
+ },
5263
+ list(body) {
5264
+ return body;
5265
+ },
5266
+ listitem(text) {
5267
+ return text;
5268
+ },
5269
+ paragraph(text) {
5270
+ return text;
5271
+ },
5272
+ codespan(text) {
5273
+ return text;
5274
+ },
5275
+ code(code) {
5276
+ return code;
5277
+ },
5278
+ heading(text) {
5279
+ return `${text}\n`;
5280
+ },
5281
+ };
5282
+ marked_1.marked.use({ renderer });
5283
+ return marked_1.marked.parse(markdown);
5284
+ }
5285
+ function mapSnykIacTestResultsToSarifResults(results) {
5286
+ const result = [];
5287
+ if (!(results === null || results === void 0 ? void 0 : results.vulnerabilities)) {
5288
+ return result;
5272
5289
  }
5290
+ results.vulnerabilities.forEach((vulnerability) => {
5291
+ var _a;
5292
+ result.push({
5293
+ ruleId: vulnerability.rule.id,
5294
+ message: {
5295
+ text: `This line contains a potential ${vulnerability.severity} severity misconfiguration`,
5296
+ },
5297
+ locations: [
5298
+ {
5299
+ physicalLocation: {
5300
+ artifactLocation: {
5301
+ uri: vulnerability.resource.file,
5302
+ uriBaseId: PROJECT_ROOT_KEY,
5303
+ },
5304
+ // We exclude the `region` key when the line number is missing or -1.
5305
+ // https://docs.oasis-open.org/sarif/sarif/v2.0/csprd02/sarif-v2.0-csprd02.html#_Toc10127873
5306
+ region: {
5307
+ startLine: (_a = vulnerability.resource.line) !== null && _a !== void 0 ? _a : 1,
5308
+ },
5309
+ },
5310
+ },
5311
+ ],
5312
+ });
5313
+ });
5314
+ return result;
5273
5315
  }
5274
- exports.lookupLocalPolicyEngine = lookupLocalPolicyEngine;
5275
-
5276
-
5277
- /***/ }),
5278
-
5279
- /***/ 22964:
5280
- /***/ ((__unused_webpack_module, exports) => {
5281
-
5282
- "use strict";
5283
-
5284
- Object.defineProperty(exports, "__esModule", ({ value: true }));
5285
- exports.rulesBundleName = void 0;
5286
- exports.rulesBundleName = 'bundle-experimental.tar.gz';
5287
5316
 
5288
5317
 
5289
5318
  /***/ }),
5290
5319
 
5291
- /***/ 30753:
5320
+ /***/ 50277:
5292
5321
  /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
5293
5322
 
5294
5323
  "use strict";
5295
5324
 
5325
+ var _a;
5296
5326
  Object.defineProperty(exports, "__esModule", ({ value: true }));
5297
- exports.FailedToCacheRulesBundleError = exports.FailedToDownloadRulesBundleError = exports.rulesBundleUrl = exports.downloadRulesBundle = void 0;
5298
- const createDebugLogger = __webpack_require__(15158);
5299
- const path = __webpack_require__(85622);
5300
- const error_utils_1 = __webpack_require__(36401);
5301
- const types_1 = __webpack_require__(94820);
5327
+ exports.scan = exports.systemCachePath = void 0;
5328
+ const childProcess = __webpack_require__(63129);
5302
5329
  const errors_1 = __webpack_require__(55191);
5303
- const metrics_1 = __webpack_require__(32971);
5304
- const file_utils_1 = __webpack_require__(52761);
5305
- const utils_1 = __webpack_require__(42256);
5306
- const constants_1 = __webpack_require__(22964);
5307
- const debugLog = createDebugLogger('snyk-iac');
5308
- async function downloadRulesBundle(testConfig) {
5309
- let downloadDurationSeconds = 0;
5310
- const timer = new metrics_1.TimerMetricInstance('iac_rules_bundle_download');
5311
- timer.start();
5312
- const dataBuffer = await fetch();
5313
- const cachedRulesBundlePath = await cache(dataBuffer, testConfig.iacCachePath);
5314
- timer.stop();
5315
- downloadDurationSeconds = Math.round(timer.getValue() / 1000);
5316
- debugLog(`Downloaded and cached rules bundle successfully in ${downloadDurationSeconds} seconds`);
5317
- return cachedRulesBundlePath;
5330
+ const types_1 = __webpack_require__(94820);
5331
+ const error_utils_1 = __webpack_require__(36401);
5332
+ const newDebug = __webpack_require__(15158);
5333
+ const results_1 = __webpack_require__(89752);
5334
+ const os = __webpack_require__(12087);
5335
+ const fs = __webpack_require__(35747);
5336
+ const path = __webpack_require__(85622);
5337
+ const rimraf = __webpack_require__(50984);
5338
+ const config_1 = __webpack_require__(25425);
5339
+ const api_token_1 = __webpack_require__(95181);
5340
+ const analytics_1 = __webpack_require__(82744);
5341
+ const env_paths_1 = __webpack_require__(21766);
5342
+ const debug = newDebug('snyk-iac');
5343
+ exports.systemCachePath = (_a = config_1.default.CACHE_PATH) !== null && _a !== void 0 ? _a : env_paths_1.default('snyk').cache;
5344
+ function scan(options, policyEnginePath, rulesBundlePath) {
5345
+ const configPath = createConfig(options);
5346
+ try {
5347
+ return scanWithConfig(options, policyEnginePath, rulesBundlePath, configPath);
5348
+ }
5349
+ finally {
5350
+ deleteConfig(configPath);
5351
+ }
5318
5352
  }
5319
- exports.downloadRulesBundle = downloadRulesBundle;
5320
- async function fetch() {
5321
- debugLog(`Fetching rules bundle from ${exports.rulesBundleUrl}`);
5322
- let rulesBundleDataBuffer;
5353
+ exports.scan = scan;
5354
+ function scanWithConfig(options, policyEnginePath, rulesBundlePath, configPath) {
5355
+ const args = processFlags(options, rulesBundlePath, configPath);
5356
+ args.push(...options.paths);
5357
+ const process = childProcess.spawnSync(policyEnginePath, args, {
5358
+ encoding: 'utf-8',
5359
+ stdio: 'pipe',
5360
+ maxBuffer: 1024 * 1024 * 10,
5361
+ });
5362
+ debug('policy engine standard error:\n%s', '\n' + process.stderr);
5363
+ if (process.status && process.status !== 0) {
5364
+ throw new ScanError(`invalid exit status: ${process.status}`);
5365
+ }
5366
+ if (process.error) {
5367
+ throw new ScanError(`spawning process: ${process.error}`);
5368
+ }
5369
+ let snykIacTestOutput;
5323
5370
  try {
5324
- rulesBundleDataBuffer = await utils_1.fetchCacheResource(exports.rulesBundleUrl);
5371
+ snykIacTestOutput = JSON.parse(process.stdout);
5325
5372
  }
5326
- catch (err) {
5327
- throw new FailedToDownloadRulesBundleError();
5373
+ catch (e) {
5374
+ throw new ScanError(`invalid output encoding: ${e}`);
5328
5375
  }
5329
- debugLog('Rules bundle was fetched successfully');
5330
- return rulesBundleDataBuffer;
5376
+ return results_1.mapSnykIacTestOutputToTestOutput(snykIacTestOutput);
5331
5377
  }
5332
- exports.rulesBundleUrl = 'https://static.snyk.io/cli/wasm/bundle-experimental.tar.gz';
5333
- class FailedToDownloadRulesBundleError extends errors_1.CustomError {
5334
- constructor() {
5335
- super(`Failed to download cache resource from ${exports.rulesBundleUrl}`);
5336
- this.code = types_1.IaCErrorCodes.FailedToDownloadRulesBundleError;
5337
- this.strCode = error_utils_1.getErrorStringCode(this.code);
5338
- this.userMessage =
5339
- `Could not fetch cache resource from: ${exports.rulesBundleUrl}` +
5340
- '\nEnsure valid network connection.';
5378
+ function processFlags(options, rulesBundlePath, configPath) {
5379
+ var _a, _b, _c;
5380
+ const flags = [
5381
+ '-cache-dir',
5382
+ exports.systemCachePath,
5383
+ '-bundle',
5384
+ rulesBundlePath,
5385
+ '-config',
5386
+ configPath,
5387
+ ];
5388
+ if (options.severityThreshold) {
5389
+ flags.push('-severity-threshold', options.severityThreshold);
5390
+ }
5391
+ if ((_a = options.attributes) === null || _a === void 0 ? void 0 : _a.criticality) {
5392
+ flags.push('-project-business-criticality', options.attributes.criticality.join(','));
5393
+ }
5394
+ if ((_b = options.attributes) === null || _b === void 0 ? void 0 : _b.environment) {
5395
+ flags.push('-project-environment', options.attributes.environment.join(','));
5396
+ }
5397
+ if ((_c = options.attributes) === null || _c === void 0 ? void 0 : _c.lifecycle) {
5398
+ flags.push('-project-lifecycle', options.attributes.lifecycle.join(','));
5399
+ }
5400
+ if (options.projectTags) {
5401
+ const stringifiedTags = options.projectTags
5402
+ .map((tag) => {
5403
+ return `${tag.key}=${tag.value}`;
5404
+ })
5405
+ .join(',');
5406
+ flags.push('-project-tags', stringifiedTags);
5407
+ }
5408
+ if (options.report) {
5409
+ flags.push('-report');
5341
5410
  }
5411
+ if (options.targetReference) {
5412
+ flags.push('-target-reference', options.targetReference);
5413
+ }
5414
+ if (options.targetName) {
5415
+ flags.push('-target-name', options.targetName);
5416
+ }
5417
+ if (options.scan) {
5418
+ flags.push('-scan', options.scan);
5419
+ }
5420
+ if (options.remoteRepoUrl) {
5421
+ flags.push('-remote-repo-url', options.remoteRepoUrl);
5422
+ }
5423
+ return flags;
5342
5424
  }
5343
- exports.FailedToDownloadRulesBundleError = FailedToDownloadRulesBundleError;
5344
- async function cache(dataBuffer, iacCachePath) {
5345
- const savePath = path.join(iacCachePath, constants_1.rulesBundleName);
5346
- debugLog(`Caching rules bundle to ${savePath}`);
5425
+ function createConfig(options) {
5347
5426
  try {
5348
- await file_utils_1.saveFile(dataBuffer, savePath);
5427
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'snyk-'));
5428
+ const tempConfig = path.join(tempDir, 'config.json');
5429
+ const configData = JSON.stringify({
5430
+ org: options.orgSettings.meta.org,
5431
+ apiUrl: config_1.default.API,
5432
+ apiAuth: api_token_1.getAuthHeader(),
5433
+ allowAnalytics: analytics_1.allowAnalytics(),
5434
+ policy: options.policy,
5435
+ });
5436
+ fs.writeFileSync(tempConfig, configData);
5437
+ return tempConfig;
5349
5438
  }
5350
- catch (err) {
5351
- throw new FailedToCacheRulesBundleError(savePath);
5439
+ catch (e) {
5440
+ throw new ScanError(`unable to create config file: ${e}`);
5352
5441
  }
5353
- debugLog(`Rules bundle was successfully cached`);
5354
- return savePath;
5355
5442
  }
5356
- class FailedToCacheRulesBundleError extends errors_1.CustomError {
5357
- constructor(savePath) {
5358
- super(`Failed to cache rules bundle to ${savePath}`);
5359
- this.code = types_1.IaCErrorCodes.FailedToCacheRulesBundleError;
5360
- this.strCode = error_utils_1.getErrorStringCode(this.code);
5361
- this.userMessage =
5362
- `Could not write the downloaded cache resource to: ${savePath}` +
5363
- '\nEnsure the cache directory is writable.';
5443
+ function deleteConfig(configPath) {
5444
+ try {
5445
+ rimraf.sync(path.dirname(configPath));
5446
+ }
5447
+ catch (e) {
5448
+ debug('unable to delete temporary directory', e);
5364
5449
  }
5365
5450
  }
5366
- exports.FailedToCacheRulesBundleError = FailedToCacheRulesBundleError;
5367
-
5368
-
5369
- /***/ }),
5370
-
5371
- /***/ 82373:
5372
- /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
5373
-
5374
- "use strict";
5375
-
5376
- Object.defineProperty(exports, "__esModule", ({ value: true }));
5377
- exports.initRulesBundle = void 0;
5378
- const createDebugLogger = __webpack_require__(15158);
5379
- const download_1 = __webpack_require__(30753);
5380
- const debugLogger = createDebugLogger('snyk-iac');
5381
- async function initRulesBundle(testConfig) {
5382
- // We are currently using the legacy rules bundle and we need to redownload it each time to use the latest one available.
5383
- // debugLogger('Looking for rules bundle locally');
5384
- // let rulesBundlePath = await lookupLocalRulesBundle(testConfig);
5385
- debugLogger(`Downloading the rules bundle and saving it at ${testConfig.iacCachePath}`);
5386
- const rulesBundlePath = await download_1.downloadRulesBundle(testConfig);
5387
- return rulesBundlePath;
5451
+ class ScanError extends errors_1.CustomError {
5452
+ constructor(message) {
5453
+ super(message);
5454
+ this.code = types_1.IaCErrorCodes.PolicyEngineScanError;
5455
+ this.strCode = error_utils_1.getErrorStringCode(this.code);
5456
+ this.userMessage = 'An error occurred when running the scan';
5457
+ }
5388
5458
  }
5389
- exports.initRulesBundle = initRulesBundle;
5390
5459
 
5391
5460
 
5392
5461
  /***/ }),
5393
5462
 
5394
- /***/ 42256:
5463
+ /***/ 89752:
5395
5464
  /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
5396
5465
 
5397
5466
  "use strict";
5398
5467
 
5399
5468
  Object.defineProperty(exports, "__esModule", ({ value: true }));
5400
- exports.fetchCacheResource = exports.InvalidUserPathError = exports.lookupLocal = void 0;
5401
- const createDebugLogger = __webpack_require__(15158);
5402
- const path = __webpack_require__(85622);
5403
- const errors_1 = __webpack_require__(55191);
5404
- const request_1 = __webpack_require__(52050);
5405
- const debugLogger = createDebugLogger('snyk-iac');
5406
- async function lookupLocal(iacCachePath, resourceName, userResourcePath, validResourceCondition) {
5407
- // Lookup in custom path.
5408
- if (userResourcePath) {
5409
- debugLogger('User configured path detected: %s', userResourcePath);
5410
- if (await validResourceCondition(userResourcePath)) {
5411
- return userResourcePath;
5412
- }
5413
- else {
5414
- // When using this function please catch this Error and throw a new specific Custom Error.
5415
- throw new InvalidUserPathError(`Failed to find a valid resource in the configured path: ${userResourcePath}`);
5416
- }
5417
- }
5418
- // Lookup in cache.
5419
- else {
5420
- const cachedResourcePath = path.join(iacCachePath, resourceName);
5421
- if (await validResourceCondition(cachedResourcePath)) {
5422
- return cachedResourcePath;
5423
- }
5424
- }
5425
- }
5426
- exports.lookupLocal = lookupLocal;
5427
- class InvalidUserPathError extends errors_1.CustomError {
5428
- constructor(message) {
5429
- super(message);
5430
- }
5431
- }
5432
- exports.InvalidUserPathError = InvalidUserPathError;
5433
- async function fetchCacheResource(url) {
5434
- const { res, body: cacheResourceBuffer } = await request_1.makeRequest({
5435
- url,
5436
- });
5437
- if (res.statusCode !== 200) {
5438
- throw new errors_1.CustomError(`Failed to download cache resource from ${url}`);
5469
+ exports.mapSnykIacTestOutputToTestOutput = void 0;
5470
+ const errors_1 = __webpack_require__(87198);
5471
+ function mapSnykIacTestOutputToTestOutput(snykIacOutput) {
5472
+ var _a;
5473
+ const errors = (_a = snykIacOutput.errors) === null || _a === void 0 ? void 0 : _a.map((err) => new errors_1.SnykIacTestError(err));
5474
+ const errWithoutPath = errors === null || errors === void 0 ? void 0 : errors.find((err) => { var _a; return !((_a = err.fields) === null || _a === void 0 ? void 0 : _a.path); });
5475
+ if (errWithoutPath) {
5476
+ throw errWithoutPath;
5439
5477
  }
5440
- return cacheResourceBuffer;
5478
+ return {
5479
+ results: snykIacOutput.results,
5480
+ errors,
5481
+ };
5441
5482
  }
5442
- exports.fetchCacheResource = fetchCacheResource;
5483
+ exports.mapSnykIacTestOutputToTestOutput = mapSnykIacTestOutputToTestOutput;
5443
5484
 
5444
5485
 
5445
5486
  /***/ }),