@codacy/tools-trivy-0 0.23.1 → 0.25.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
@@ -12,6 +12,7 @@
12
12
  - [Known divergences](#known-divergences)
13
13
  - [DB update management](#db-update-management)
14
14
  - [Malicious package detection](#malicious-package-detection)
15
+ - [Container image mode](#container-image-mode)
15
16
  - [Updating patterns](#updating-patterns)
16
17
  - [Updating the Trivy version](#updating-the-trivy-version)
17
18
  - [Development](#development)
@@ -177,6 +178,34 @@ is extracted and cross-referenced against the OpenSSF malicious packages index (
177
178
  - On API failure (network error, timeout), logs a warning and skips — never blocks the core scan
178
179
  - Message format: `Malicious package detected: {name}@{version} ({MAL-ID}). {summary}`
179
180
 
181
+ ## Container image mode
182
+
183
+ Besides the repository scan, the adapter implements the optional `containerImage` capability
184
+ (`src/image.ts`), which backs the CLI's `container-scan` and `upload-sbom` commands. The descriptor
185
+ advertises it with `scansContainerImages: true`.
186
+
187
+ | Method | Invocation |
188
+ | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
189
+ | `scan` | `trivy image --format json --cache-dir … [--skip-db-update --skip-java-db-update] --scanners vuln [--ignore-unfixed] --severity … --pkg-types … <image>` |
190
+ | `generateSbom` | `trivy image --format cyclonedx\|spdx-json --output <path> --cache-dir … <image>` |
191
+
192
+ - The image reference is re-validated with `validateImageReference` right before it becomes an argv
193
+ element, even though the runner validated it first.
194
+ - `--exit-code` is deliberately **not** passed. The finding count comes from the parsed JSON, so any
195
+ non-zero exit is a real failure — no stderr heuristics like cli-v2's to decide _whether_ it failed.
196
+ - Findings reuse `describeVulnerability` (`src/findings.ts`), the same mapping the repository scan
197
+ uses: umbrella pattern by severity, `codacy-trivy`'s message format, CVE as `sourceId`, `UNKNOWN`
198
+ dropped. The location is Trivy's `Target` (the OS layer or an in-image manifest) at line 1.
199
+ - `generateSbom` succeeds only if Trivy exits 0 **and** wrote a non-empty file.
200
+ - Every Trivy spawn (both modes) sets `TRIVY_SKIP_VERSION_CHECK=true`, and a failure's stderr goes
201
+ through `summarizeTrivyStderr` (`src/trivy-errors.ts`) rather than being echoed: Trivy's stderr is
202
+ a log stream (INFO lines, an ANSI version notice, then a FATAL Go error-wrap chain), and the text
203
+ formatter truncates errors at 240 characters, which used to cut it off before the cause. The env
204
+ var rather than `--skip-version-check`, because an older global Trivy would reject the flag.
205
+ - `test/fixtures/image-scan.json` is trimmed from a real `trivy image` run against
206
+ `nginx:1.21.0-alpine`, plus one synthetic `UNKNOWN` finding and one synthetic library finding.
207
+ `CODACY_TRIVY_IMAGE_IT=1 pnpm test` runs the opt-in integration test against the real registry.
208
+
180
209
  ## Updating patterns
181
210
 
182
211
  ```bash
@@ -189,7 +218,7 @@ git add src/patterns.json
189
218
 
190
219
  ## Updating the Trivy version
191
220
 
192
- 1. Update `preferredVersion` in `src/adapter.ts`
221
+ 1. Update `preferredVersion` in `src/metadata.ts`
193
222
  2. Update the download URL template if the release format changed
194
223
  3. Run `pnpm test` to verify compatibility
195
224
 
package/dist/index.js CHANGED
@@ -233,18 +233,19 @@ var patterns_default = [
233
233
  // src/metadata.ts
234
234
  var descriptor = {
235
235
  id: "Trivy",
236
+ shortName: "trivy",
236
237
  displayName: "Trivy",
237
238
  preferredVersion: "0.72.0",
238
239
  languages: [
239
240
  "Python",
240
- "JavaScript",
241
+ "Javascript",
241
242
  "TypeScript",
242
243
  "Go",
243
244
  "Java",
244
245
  "Ruby",
245
246
  "Rust",
246
247
  "PHP",
247
- "C#",
248
+ "CSharp",
248
249
  "Dart",
249
250
  "Elixir",
250
251
  "Swift"
@@ -257,7 +258,9 @@ var descriptor = {
257
258
  // issues must upload `sourceId` (the CVE id) or two CVEs on the same manifest
258
259
  // line collapse into a single Codacy result. Matches `needs_source_id_upload`
259
260
  // in the Go CLI's Trivy plugin manifest.
260
- needsSourceIdUpload: true
261
+ needsSourceIdUpload: true,
262
+ // Implements `containerImage` (`trivy image`) for `container-scan` / `upload-sbom`.
263
+ scansContainerImages: true
261
264
  };
262
265
 
263
266
  // src/vuln-mapping.ts
@@ -366,8 +369,7 @@ function comparePrerelease(x, y) {
366
369
  return xs.length < ys.length ? -1 : 1;
367
370
  }
368
371
 
369
- // src/adapter.ts
370
- var TOOL_ID = "Trivy";
372
+ // src/findings.ts
371
373
  var PATTERN_META = new Map(
372
374
  patterns_default.map((p) => [
373
375
  p.id,
@@ -383,6 +385,158 @@ var VULN_SEVERITY_TO_PATTERN = {
383
385
  MEDIUM: "Trivy_vulnerability_medium",
384
386
  LOW: "Trivy_vulnerability_minor"
385
387
  };
388
+ function describeVulnerability(vuln) {
389
+ const patternId = VULN_SEVERITY_TO_PATTERN[vuln.Severity];
390
+ if (!patternId) return void 0;
391
+ const meta = PATTERN_META.get(patternId) ?? {
392
+ category: "Security",
393
+ severity: "Info"
394
+ };
395
+ const fixedVersion = findLeastDisruptiveFixedVersion(
396
+ vuln.InstalledVersion,
397
+ vuln.FixedVersion ?? ""
398
+ );
399
+ const fix = fixedVersion ? `(update to ${fixedVersion})` : "(no fix available)";
400
+ const purl = vuln.PkgIdentifier?.PURL;
401
+ const pkgLabel = purl ? purlPrettyPrint(purl) : `${vuln.PkgName}@${vuln.InstalledVersion}`;
402
+ return {
403
+ patternId,
404
+ message: `Insecure dependency ${pkgLabel} (${vuln.VulnerabilityID}: ${vuln.Title ?? ""}) ${fix}`,
405
+ category: meta.category,
406
+ severity: meta.severity,
407
+ ...vuln.VulnerabilityID ? { sourceId: vuln.VulnerabilityID } : {}
408
+ };
409
+ }
410
+
411
+ // src/image.ts
412
+ function buildImageScanArgs(base, options) {
413
+ const args = [
414
+ "image",
415
+ "--format",
416
+ "json",
417
+ "--cache-dir",
418
+ base.cacheDir,
419
+ ...dbUpdateArgs(base),
420
+ "--scanners",
421
+ "vuln"
422
+ ];
423
+ if (options.ignoreUnfixed) args.push("--ignore-unfixed");
424
+ args.push("--severity", options.severities.join(","));
425
+ args.push("--pkg-types", options.pkgTypes.join(","));
426
+ args.push(options.image);
427
+ return args;
428
+ }
429
+ function buildSbomArgs(base, options) {
430
+ return [
431
+ "image",
432
+ "--format",
433
+ options.format,
434
+ "--output",
435
+ options.outputPath,
436
+ "--cache-dir",
437
+ base.cacheDir,
438
+ options.image
439
+ ];
440
+ }
441
+ function dbUpdateArgs(base) {
442
+ return base.skipDbUpdate ? ["--skip-db-update", "--skip-java-db-update"] : [];
443
+ }
444
+ function parseImageVulnerabilities(output, toolId) {
445
+ const issues = [];
446
+ for (const result of output.Results ?? []) {
447
+ for (const vuln of result.Vulnerabilities ?? []) {
448
+ const described = describeVulnerability(vuln);
449
+ if (!described) continue;
450
+ issues.push({
451
+ ...described,
452
+ filePath: result.Target,
453
+ toolId,
454
+ line: 1,
455
+ column: 1,
456
+ lineContent: ""
457
+ });
458
+ }
459
+ }
460
+ return issues;
461
+ }
462
+
463
+ // src/trivy-errors.ts
464
+ var TRIVY_ENV = { TRIVY_SKIP_VERSION_CHECK: "true" };
465
+ function stripAnsi(text) {
466
+ return text.replace(/\x1b\[[0-9;]*[A-Za-z]/g, "");
467
+ }
468
+ var WRAPPER_PREFIXES = [
469
+ /^run error:\s*/i,
470
+ /^(?:image|fs|filesystem|repository|rootfs|sbom|vm) scan error:\s*/i,
471
+ /^scan error:\s*/i,
472
+ /^unable to initialize (?:a scan service|artifact|container image):\s*/i
473
+ ];
474
+ function stripWrappers(chain) {
475
+ let current = chain.trim();
476
+ let changed = true;
477
+ while (changed) {
478
+ changed = false;
479
+ for (const prefix of WRAPPER_PREFIXES) {
480
+ const next = current.replace(prefix, "");
481
+ if (next !== current) {
482
+ current = next;
483
+ changed = true;
484
+ }
485
+ }
486
+ }
487
+ return current;
488
+ }
489
+ function summarizeTrivyStderr(stderr) {
490
+ const text = stripAnsi(stderr);
491
+ const lines = text.split(/\r?\n/);
492
+ const fatalIndex = lines.findIndex((l) => /\tFATAL\t|\sFATAL\s/.test(l));
493
+ if (fatalIndex !== -1) {
494
+ const chain = lines[fatalIndex].replace(/^.*?\bFATAL\s+(?:Fatal error\s+)?/, "");
495
+ const details = lines.slice(fatalIndex + 1).map((l) => l.trim());
496
+ const missing = chain.match(/unable to find the specified image "([^"]+)"/);
497
+ if (missing) {
498
+ const remote = details.find((l) => /^\*\s*remote error:/i.test(l))?.replace(/^\*\s*remote error:\s*/i, "");
499
+ const base = `Image "${missing[1]}" not found locally (Docker, containerd, Podman) or in its registry`;
500
+ if (!remote) return base;
501
+ if (/UNAUTHORIZED|authentication required|denied/i.test(remote)) {
502
+ return `${base}: access denied \u2014 the image or tag does not exist, or it is private and needs a registry login`;
503
+ }
504
+ return `${base}: ${remote.replace(/\s*\[map\[.*$/, "")}`;
505
+ }
506
+ return stripWrappers(chain).replace(/:\s*\d+ errors? occurred:?$/i, "");
507
+ }
508
+ return withoutNoise(lines).join(" ");
509
+ }
510
+ var TIMESTAMPED = /^\d{4}-\d{2}-\d{2}T\S+\s+/;
511
+ var QUIET_LOG_LINE = /^\d{4}-\d{2}-\d{2}T\S+\s+(?:DEBUG|INFO)\b/;
512
+ function withoutNoise(lines) {
513
+ const kept = [];
514
+ let inNotice = false;
515
+ for (const raw of lines) {
516
+ const line = raw.trim();
517
+ if (/Notices:/.test(line)) {
518
+ inNotice = true;
519
+ continue;
520
+ }
521
+ if (inNotice) {
522
+ if (/--skip-version-check/.test(line)) {
523
+ inNotice = false;
524
+ continue;
525
+ }
526
+ if (!TIMESTAMPED.test(line)) continue;
527
+ inNotice = false;
528
+ }
529
+ if (line.length === 0 || QUIET_LOG_LINE.test(line)) continue;
530
+ kept.push(line.replace(TIMESTAMPED, "").replace(/\t/g, " "));
531
+ }
532
+ return kept;
533
+ }
534
+ function trivyExitMessage(exitCode, stderr) {
535
+ return summarizeTrivyStderr(stderr) || `trivy exited with code ${exitCode}`;
536
+ }
537
+
538
+ // src/adapter.ts
539
+ var TOOL_ID = "Trivy";
386
540
  var PATTERN_TO_SEVERITY = {
387
541
  Trivy_vulnerability_critical: "CRITICAL",
388
542
  Trivy_vulnerability_high: "HIGH",
@@ -443,7 +597,11 @@ var PLATFORM_MAP = {
443
597
  "linux-arm64": "Linux-ARM64",
444
598
  // Windows ships a `.zip` (trivy_{version}_windows-64bit.zip) with `trivy.exe`
445
599
  // at the archive root — handled in install (extension + exeName).
446
- "win32-x64": "windows-64bit"
600
+ "win32-x64": "windows-64bit",
601
+ // Trivy publishes no Windows ARM64 build; Windows on ARM runs the x64 binary
602
+ // under emulation, so use it rather than reporting the platform unsupported
603
+ // (the descriptor already declares arm64).
604
+ "win32-arm64": "windows-64bit"
447
605
  };
448
606
  async function getVersionFromBinary(binaryPath) {
449
607
  try {
@@ -486,14 +644,18 @@ async function checkDbFreshness(cacheDir) {
486
644
  return { fresh: false, error: message };
487
645
  }
488
646
  }
489
- async function runTrivyScan(binary, args, cwd, errors) {
490
- const { stdout, stderr, exitCode } = await (0, import_tooling.spawnTool)(binary, args, { cwd });
647
+ async function runTrivyScan(binary, args, cwd, errors, spawnOptions = {}) {
648
+ const { stdout, stderr, exitCode } = await (0, import_tooling.spawnTool)(binary, args, {
649
+ cwd,
650
+ env: TRIVY_ENV,
651
+ ...spawnOptions
652
+ });
491
653
  if (exitCode !== 0) {
492
654
  errors.push({
493
655
  toolId: TOOL_ID,
494
656
  phase: "toolInvoke",
495
657
  kind: "NonZeroExit",
496
- message: `trivy exited with code ${exitCode}${stderr ? `: ${stderr.trim()}` : ""}`,
658
+ message: trivyExitMessage(exitCode, stderr),
497
659
  level: "error"
498
660
  });
499
661
  return null;
@@ -514,7 +676,6 @@ async function runTrivyScan(binary, args, cwd, errors) {
514
676
  return null;
515
677
  }
516
678
  }
517
- var LINE_NUMBERS_NOT_SUPPORTED = "Line numbers not supported";
518
679
  function recordUnlocatableFinding(errors, seenFiles, filePath) {
519
680
  if (seenFiles.has(filePath)) return;
520
681
  seenFiles.add(filePath);
@@ -522,9 +683,10 @@ function recordUnlocatableFinding(errors, seenFiles, filePath) {
522
683
  toolId: TOOL_ID,
523
684
  phase: "outputParse",
524
685
  kind: "LineNumbersNotSupported",
525
- message: LINE_NUMBERS_NOT_SUPPORTED,
686
+ message: import_tooling.LINE_NUMBERS_NOT_SUPPORTED,
526
687
  level: "warning",
527
- filePath
688
+ filePath,
689
+ fileNotAnalyzed: true
528
690
  });
529
691
  }
530
692
  async function parseVulnerabilities(output, enabledPatterns, targetFilesSet, repositoryRoot, unlocatableFiles) {
@@ -556,13 +718,9 @@ async function parseVulnerabilities(output, enabledPatterns, targetFilesSet, rep
556
718
  return found;
557
719
  };
558
720
  for (const vuln of result.Vulnerabilities) {
559
- const patternId = VULN_SEVERITY_TO_PATTERN[vuln.Severity];
560
- if (!patternId) continue;
561
- if (enabledPatterns.size > 0 && !enabledPatterns.has(patternId)) continue;
562
- const meta = PATTERN_META.get(patternId) ?? {
563
- category: "Security",
564
- severity: "Info"
565
- };
721
+ const described = describeVulnerability(vuln);
722
+ if (!described) continue;
723
+ if (enabledPatterns.size > 0 && !enabledPatterns.has(described.patternId)) continue;
566
724
  const purl = vuln.PkgIdentifier?.PURL;
567
725
  const reportedLine = (purl !== void 0 ? lineByPurl.get(purl) : void 0) ?? (vuln.PkgID !== void 0 ? lineByPkgId.get(vuln.PkgID) : void 0) ?? 0;
568
726
  const line = reportedLine > 0 ? reportedLine : resolveFallbackLine(vuln.PkgName);
@@ -570,23 +728,13 @@ async function parseVulnerabilities(output, enabledPatterns, targetFilesSet, rep
570
728
  recordUnlocatableFinding(errors, unlocatableFiles, relPath);
571
729
  continue;
572
730
  }
573
- const fixedVersion = findLeastDisruptiveFixedVersion(
574
- vuln.InstalledVersion,
575
- vuln.FixedVersion ?? ""
576
- );
577
- const fix = fixedVersion ? `(update to ${fixedVersion})` : "(no fix available)";
578
- const pkgLabel = purl ? purlPrettyPrint(purl) : `${vuln.PkgName}@${vuln.InstalledVersion}`;
579
731
  issues.push({
732
+ ...described,
580
733
  filePath: relPath,
581
- patternId,
582
734
  toolId: TOOL_ID,
583
735
  line,
584
736
  column: 1,
585
- message: `Insecure dependency ${pkgLabel} (${vuln.VulnerabilityID}: ${vuln.Title ?? ""}) ${fix}`,
586
- lineContent: (0, import_tooling.getLineContent)(lines, line),
587
- category: meta.category,
588
- severity: meta.severity,
589
- ...vuln.VulnerabilityID ? { sourceId: vuln.VulnerabilityID } : {}
737
+ lineContent: (0, import_tooling.getLineContent)(lines, line)
590
738
  });
591
739
  }
592
740
  }
@@ -737,12 +885,101 @@ async function parseMaliciousPackages(output, enabledPatterns, targetFilesSet, r
737
885
  logger.info("Malicious package check complete", { issuesFound: issues.length });
738
886
  return { issues, errors };
739
887
  }
888
+ async function scanImage(ctx, options) {
889
+ const startedAt = /* @__PURE__ */ new Date();
890
+ const errors = [];
891
+ const fail = (kind, message) => {
892
+ errors.push({ toolId: TOOL_ID, phase: "toolInvoke", kind, message, level: "error" });
893
+ const result = (0, import_tooling.buildResult)(TOOL_ID, startedAt, /* @__PURE__ */ new Date(), [], errors, 0);
894
+ return { ...result, summary: { ...result.summary, status: "failed" } };
895
+ };
896
+ try {
897
+ (0, import_tooling.validateImageReference)(options.image);
898
+ } catch (err) {
899
+ return fail("InvalidImageReference", errorMessage(err));
900
+ }
901
+ ctx.logger.info("Starting image scan", { toolId: TOOL_ID, image: options.image });
902
+ try {
903
+ const binary = await resolveBinaryPath(ctx);
904
+ const cacheDir = await ensureCacheDir(ctx.globalDir);
905
+ const skipDbUpdate = await shouldSkipDbUpdate(ctx, cacheDir);
906
+ const args = buildImageScanArgs({ cacheDir, skipDbUpdate }, options);
907
+ const output = await runTrivyScan(binary, args, ctx.repositoryRoot, errors, {
908
+ signal: ctx.signal,
909
+ logger: ctx.logger
910
+ });
911
+ if (!output) {
912
+ const result = (0, import_tooling.buildResult)(TOOL_ID, startedAt, /* @__PURE__ */ new Date(), [], errors, 0);
913
+ return { ...result, summary: { ...result.summary, status: "failed" } };
914
+ }
915
+ const issues = parseImageVulnerabilities(output, TOOL_ID);
916
+ ctx.logger.info("Image scan complete", { toolId: TOOL_ID, issueCount: issues.length });
917
+ return (0, import_tooling.buildResult)(TOOL_ID, startedAt, /* @__PURE__ */ new Date(), issues, errors, 1);
918
+ } catch (err) {
919
+ if (ctx.signal?.aborted) return fail("Cancelled", "Image scan cancelled by caller");
920
+ return fail("InvocationError", `Failed to run trivy: ${errorMessage(err)}`);
921
+ }
922
+ }
923
+ async function generateImageSbom(ctx, options) {
924
+ const failure = (kind, message) => ({
925
+ success: false,
926
+ error: { toolId: TOOL_ID, phase: "toolInvoke", kind, message, level: "error" }
927
+ });
928
+ try {
929
+ (0, import_tooling.validateImageReference)(options.image);
930
+ } catch (err) {
931
+ return failure("InvalidImageReference", errorMessage(err));
932
+ }
933
+ try {
934
+ const binary = await resolveBinaryPath(ctx);
935
+ const cacheDir = await ensureCacheDir(ctx.globalDir);
936
+ const args = buildSbomArgs({ cacheDir }, options);
937
+ ctx.logger.info("Generating SBOM", { toolId: TOOL_ID, image: options.image });
938
+ const { stderr, exitCode } = await (0, import_tooling.spawnTool)(binary, args, {
939
+ cwd: ctx.repositoryRoot,
940
+ env: TRIVY_ENV,
941
+ logger: ctx.logger,
942
+ signal: ctx.signal
943
+ });
944
+ if (exitCode !== 0) {
945
+ return failure("NonZeroExit", trivyExitMessage(exitCode, stderr));
946
+ }
947
+ const stat = await import_promises.default.stat(options.outputPath).catch(() => null);
948
+ if (!stat || stat.size === 0) {
949
+ return failure(
950
+ "MissingOutput",
951
+ `trivy exited cleanly but wrote no SBOM to ${options.outputPath}`
952
+ );
953
+ }
954
+ return { success: true };
955
+ } catch (err) {
956
+ if (ctx.signal?.aborted) return failure("Cancelled", "SBOM generation cancelled by caller");
957
+ return failure("InvocationError", `Failed to run trivy: ${errorMessage(err)}`);
958
+ }
959
+ }
960
+ async function shouldSkipDbUpdate(ctx, cacheDir) {
961
+ if (ctx.runner === "container") return true;
962
+ const status = await checkDbFreshness(cacheDir);
963
+ if (!status.fresh) {
964
+ ctx.logger.info(
965
+ status.error?.includes("ENOENT") ? "Trivy vulnerability database not found. Downloading (~40MB)..." : "Trivy DB update due, checking for new data..."
966
+ );
967
+ }
968
+ return status.fresh;
969
+ }
970
+ function errorMessage(err) {
971
+ return err instanceof Error ? err.message : String(err);
972
+ }
740
973
  var adapter = {
741
974
  ...descriptor,
742
975
  patternsMetadata: patterns_default,
743
976
  compatibleVersions: ">=0.50.0",
744
977
  website: "https://trivy.dev/",
745
978
  prerequisites: [],
979
+ containerImage: {
980
+ scan: scanImage,
981
+ generateSbom: generateImageSbom
982
+ },
746
983
  /**
747
984
  * Checks whether the `trivy` binary is present and runnable.
748
985
  *
@@ -789,8 +1026,9 @@ var adapter = {
789
1026
  /**
790
1027
  * Downloads trivy from GitHub releases and extracts it to ctx.toolInstallDir.
791
1028
  *
792
- * Detects the current platform/arch and downloads the appropriate tar.gz archive.
793
- * Sets executable permission after extraction.
1029
+ * Detects the current platform/arch and downloads the matching archive
1030
+ * (`.zip` on Windows, `.tar.gz` elsewhere). Sets executable permission after
1031
+ * extraction (not needed on Windows).
794
1032
  */
795
1033
  async install(ctx) {
796
1034
  ctx.logger.info("Starting install", { toolId: TOOL_ID });
@@ -809,7 +1047,7 @@ var adapter = {
809
1047
  };
810
1048
  }
811
1049
  const version = adapter.preferredVersion;
812
- const archiveExt = import_tooling.IS_WINDOWS ? "zip" : "tar.gz";
1050
+ const archiveExt = ctx.platform.os === "win32" ? "zip" : "tar.gz";
813
1051
  const url = `https://github.com/aquasecurity/trivy/releases/download/v${version}/trivy_${version}_${platformSuffix}.${archiveExt}`;
814
1052
  const destPath = import_path.default.join(ctx.toolInstallDir, (0, import_tooling.exeName)(BINARY));
815
1053
  try {
package/dist/metadata.js CHANGED
@@ -25,18 +25,19 @@ __export(metadata_exports, {
25
25
  module.exports = __toCommonJS(metadata_exports);
26
26
  var descriptor = {
27
27
  id: "Trivy",
28
+ shortName: "trivy",
28
29
  displayName: "Trivy",
29
30
  preferredVersion: "0.72.0",
30
31
  languages: [
31
32
  "Python",
32
- "JavaScript",
33
+ "Javascript",
33
34
  "TypeScript",
34
35
  "Go",
35
36
  "Java",
36
37
  "Ruby",
37
38
  "Rust",
38
39
  "PHP",
39
- "C#",
40
+ "CSharp",
40
41
  "Dart",
41
42
  "Elixir",
42
43
  "Swift"
@@ -49,7 +50,9 @@ var descriptor = {
49
50
  // issues must upload `sourceId` (the CVE id) or two CVEs on the same manifest
50
51
  // line collapse into a single Codacy result. Matches `needs_source_id_upload`
51
52
  // in the Go CLI's Trivy plugin manifest.
52
- needsSourceIdUpload: true
53
+ needsSourceIdUpload: true,
54
+ // Implements `containerImage` (`trivy image`) for `container-scan` / `upload-sbom`.
55
+ scansContainerImages: true
53
56
  };
54
57
  // Annotate the CommonJS export names for ESM import in node:
55
58
  0 && (module.exports = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codacy/tools-trivy-0",
3
- "version": "0.23.1",
3
+ "version": "0.25.0",
4
4
  "description": "Trivy adapter — CLI-mode security scanner",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -8,7 +8,7 @@
8
8
  "dist"
9
9
  ],
10
10
  "dependencies": {
11
- "@codacy/tooling": "0.23.1"
11
+ "@codacy/tooling": "0.25.0"
12
12
  },
13
13
  "license": "MIT",
14
14
  "author": "Codacy <support@codacy.com> (https://www.codacy.com)",