github-issue-tower-defence-management 1.148.6 → 1.148.7

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/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## [1.148.7](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/compare/v1.148.6...v1.148.7) (2026-08-09)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **security-scan:** select CISA KEV additions by scanned package versions ([#1481](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/issues/1481)) ([550a788](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/commit/550a788bf940d08c53e3ff5120dc6c589573f731))
7
+
1
8
  ## [1.148.6](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/compare/v1.148.5...v1.148.6) (2026-08-09)
2
9
 
3
10
 
@@ -20,6 +20,48 @@ const isKevCatalog = (value) => {
20
20
  return (Array.isArray(record.vulnerabilities) &&
21
21
  record.vulnerabilities.every(isKevVulnerability));
22
22
  };
23
+ const parseScannerVulnerabilities = (repositoryName, scannerOutput) => {
24
+ let parsed;
25
+ try {
26
+ parsed = JSON.parse(scannerOutput);
27
+ }
28
+ catch (error) {
29
+ console.error(`Unparsable osv-scanner output for ${repositoryName}: ${String(error)}`);
30
+ return [];
31
+ }
32
+ const toRecord = (value) => typeof value === 'object' && value !== null ? { ...value } : {};
33
+ const readArray = (value, key) => {
34
+ const entry = toRecord(value)[key];
35
+ return Array.isArray(entry) ? entry : [];
36
+ };
37
+ const readString = (value, key) => {
38
+ const entry = toRecord(value)[key];
39
+ return typeof entry === 'string' ? entry : '';
40
+ };
41
+ return readArray(parsed, 'results').flatMap((result) => readArray(result, 'packages').flatMap((scannedPackage) => {
42
+ const packageDetail = toRecord(scannedPackage).package;
43
+ return readArray(scannedPackage, 'vulnerabilities').map((vulnerability) => {
44
+ const vulnerabilityId = readString(vulnerability, 'id');
45
+ const aliases = readArray(vulnerability, 'aliases').filter((alias) => typeof alias === 'string');
46
+ return {
47
+ repositoryName,
48
+ ecosystem: readString(packageDetail, 'ecosystem'),
49
+ packageName: readString(packageDetail, 'name'),
50
+ packageVersion: readString(packageDetail, 'version'),
51
+ vulnerabilityId,
52
+ vulnerabilityIdentifiers: [vulnerabilityId, ...aliases],
53
+ summary: readString(vulnerability, 'summary'),
54
+ };
55
+ });
56
+ }));
57
+ };
58
+ const renderScannerFindings = (today, vulnerablePackages) => [
59
+ '## OSV-Scanner findings',
60
+ '',
61
+ `### ${today}`,
62
+ '',
63
+ ...vulnerablePackages.map((vulnerablePackage) => `- ${vulnerablePackage.ecosystem} ${vulnerablePackage.packageName} ${vulnerablePackage.packageVersion} ${vulnerablePackage.vulnerabilityIdentifiers.join(' ')} ${vulnerablePackage.summary}`),
64
+ ].join('\n');
23
65
  const KEV_CATALOG_URL = 'https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json';
24
66
  class DailySecurityScanUseCase {
25
67
  constructor(localCommandRunner, issueRepository, httpRepository) {
@@ -34,8 +76,8 @@ class DailySecurityScanUseCase {
34
76
  }
35
77
  const lastTargetDate = input.targetDates[input.targetDates.length - 1];
36
78
  const today = lastTargetDate.toISOString().slice(0, 10);
37
- await this.scanRepositories(input.org, input.manager, today, input.dailySecurityScan);
38
- await this.reportKevAdditions(input.org, input.manager, lastTargetDate, input.dailySecurityScan);
79
+ const scannedVulnerablePackages = await this.scanRepositories(input.org, input.manager, today, input.dailySecurityScan);
80
+ await this.reportKevAdditions(input.org, input.manager, lastTargetDate, input.dailySecurityScan, scannedVulnerablePackages);
39
81
  };
40
82
  this.scanRepositories = async (org, manager, today, config) => {
41
83
  const { stdout: findOutput } = await this.localCommandRunner.runCommand('find', [
@@ -53,8 +95,9 @@ class DailySecurityScanUseCase {
53
95
  .map((gitDirectory) => gitDirectory.replace(/\/\.git$/, ''));
54
96
  if (repositoryDirectories.length === 0) {
55
97
  console.error(`No repositories found in scan base directory: ${config.scanBaseDirectory}`);
56
- return;
98
+ return [];
57
99
  }
100
+ const scannedVulnerablePackages = [];
58
101
  for (const repositoryDirectory of repositoryDirectories) {
59
102
  const { stdout: remoteUrl, exitCode: remoteExitCode } = await this.localCommandRunner.runCommand('git', [
60
103
  '-C',
@@ -79,6 +122,8 @@ class DailySecurityScanUseCase {
79
122
  'source',
80
123
  '-r',
81
124
  repositoryDirectory,
125
+ '--format',
126
+ 'json',
82
127
  ]);
83
128
  if (scanExitCode === 0) {
84
129
  continue;
@@ -87,7 +132,9 @@ class DailySecurityScanUseCase {
87
132
  console.error(`osv-scanner failed with exit code ${scanExitCode} for ${repositoryDirectory}: ${scanStderr}`);
88
133
  continue;
89
134
  }
90
- const findingsBody = `## OSV-Scanner findings\n\n### ${today}\n\n\`\`\`\n${scanOutput}\n\`\`\``;
135
+ const vulnerablePackages = parseScannerVulnerabilities(repositoryName, scanOutput);
136
+ scannedVulnerablePackages.push(...vulnerablePackages);
137
+ const findingsBody = renderScannerFindings(today, vulnerablePackages);
91
138
  const existingIssues = await this.issueRepository.searchIssue({
92
139
  owner: repositoryOrg,
93
140
  repositoryName,
@@ -103,8 +150,9 @@ class DailySecurityScanUseCase {
103
150
  await this.issueRepository.createNewIssue(repositoryOrg, repositoryName, 'Daily security scan findings', findingsBody, [manager], []);
104
151
  }
105
152
  }
153
+ return scannedVulnerablePackages;
106
154
  };
107
- this.reportKevAdditions = async (org, manager, lastTargetDate, config) => {
155
+ this.reportKevAdditions = async (org, manager, lastTargetDate, config, scannedVulnerablePackages) => {
108
156
  if (!config.enableKevNvdReport || !config.kevReportRepo) {
109
157
  return;
110
158
  }
@@ -117,46 +165,22 @@ class DailySecurityScanUseCase {
117
165
  throw new Error(`Unexpected CISA KEV catalog format from ${KEV_CATALOG_URL}`);
118
166
  }
119
167
  const newKevEntries = parsedKev.vulnerabilities.filter((vulnerability) => vulnerability.dateAdded >= yesterdayYmd);
120
- const usedKevEntries = [];
121
- for (const vulnerability of newKevEntries) {
122
- if (await this.isProductPresentInScannedWorkspace(config.scanBaseDirectory, vulnerability.product)) {
123
- usedKevEntries.push(vulnerability);
124
- }
125
- }
126
- if (usedKevEntries.length === 0) {
168
+ const affectingKevEntries = newKevEntries
169
+ .map((vulnerability) => ({
170
+ vulnerability,
171
+ affectedPackages: scannedVulnerablePackages.filter((scannedPackage) => scannedPackage.vulnerabilityIdentifiers.includes(vulnerability.cveID)),
172
+ }))
173
+ .filter((entry) => entry.affectedPackages.length > 0);
174
+ if (affectingKevEntries.length === 0) {
127
175
  return;
128
176
  }
129
- await this.issueRepository.createNewIssue(org, config.kevReportRepo, `CISA KEV new additions since ${yesterdayYmd}`, usedKevEntries
130
- .map((vulnerability) => `- ${vulnerability.dateAdded} ${vulnerability.cveID} ${vulnerability.vulnerabilityName}`)
177
+ await this.issueRepository.createNewIssue(org, config.kevReportRepo, `CISA KEV new additions since ${yesterdayYmd}`, affectingKevEntries
178
+ .map((entry) => [
179
+ `- ${entry.vulnerability.dateAdded} ${entry.vulnerability.cveID} ${entry.vulnerability.vulnerabilityName}`,
180
+ ...entry.affectedPackages.map((affectedPackage) => ` - ${affectedPackage.repositoryName} ${affectedPackage.ecosystem} ${affectedPackage.packageName} ${affectedPackage.packageVersion}`),
181
+ ].join('\n'))
131
182
  .join('\n'), [manager], []);
132
183
  };
133
- this.isProductPresentInScannedWorkspace = async (scanBaseDirectory, product) => {
134
- const { stdout: findOutput } = await this.localCommandRunner.runCommand('find', [scanBaseDirectory, '-maxdepth', '3', '-name', '.git', '-type', 'd']);
135
- const repositoryDirectories = findOutput
136
- .split('\n')
137
- .filter((line) => line.length > 0)
138
- .map((gitDirectory) => gitDirectory.replace(/\/\.git$/, ''));
139
- for (const repositoryDirectory of repositoryDirectories) {
140
- const { stderr, exitCode } = await this.localCommandRunner.runCommand('git', [
141
- '-C',
142
- repositoryDirectory,
143
- 'grep',
144
- '-I',
145
- '-i',
146
- '-q',
147
- '-F',
148
- '-e',
149
- product,
150
- ]);
151
- if (exitCode === 0) {
152
- return true;
153
- }
154
- if (exitCode !== 1) {
155
- console.error(`Failed to search ${repositoryDirectory} for ${product}: ${stderr}`);
156
- }
157
- }
158
- return false;
159
- };
160
184
  }
161
185
  }
162
186
  exports.DailySecurityScanUseCase = DailySecurityScanUseCase;
@@ -1 +1 @@
1
- {"version":3,"file":"DailySecurityScanUseCase.js","sourceRoot":"","sources":["../../../src/domain/usecases/DailySecurityScanUseCase.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DailySecurityScanUseCase.js","sourceRoot":"","sources":["../../../src/domain/usecases/DailySecurityScanUseCase.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "github-issue-tower-defence-management",
3
- "version": "1.148.6",
3
+ "version": "1.148.7",
4
4
  "description": "",
5
5
  "main": "bin/index.js",
6
6
  "scripts": {
@@ -311,14 +311,53 @@ describe('DailySecurityScanUseCase', () => {
311
311
  mockHttpRepository,
312
312
  } = buildUseCase();
313
313
 
314
- mockLocalCommandRunner.runCommand.mockImplementation(
315
- async (program, args) => {
316
- if (program === 'find' && args.includes('-maxdepth')) {
317
- return { stdout: '/repos/app/.git\n', stderr: '', exitCode: 0 };
318
- }
319
- return { stdout: '', stderr: '', exitCode: 0 };
320
- },
321
- );
314
+ mockIssueRepository.searchIssue.mockResolvedValue([]);
315
+ mockLocalCommandRunner.runCommand.mockImplementation(async (program) => {
316
+ if (program === 'find') {
317
+ return {
318
+ stdout: '/repos/example-org/app/.git\n',
319
+ stderr: '',
320
+ exitCode: 0,
321
+ };
322
+ }
323
+ if (program === 'git') {
324
+ return {
325
+ stdout: 'git@github.com:example-org/app.git\n',
326
+ stderr: '',
327
+ exitCode: 0,
328
+ };
329
+ }
330
+ if (program === 'osv-scanner') {
331
+ return {
332
+ stdout: JSON.stringify({
333
+ results: [
334
+ {
335
+ source: { path: '/repos/example-org/app', type: 'lockfile' },
336
+ packages: [
337
+ {
338
+ package: {
339
+ name: 'example-library',
340
+ version: '1.2.3',
341
+ ecosystem: 'npm',
342
+ },
343
+ vulnerabilities: [
344
+ {
345
+ id: 'GHSA-1111-2222-3333',
346
+ aliases: ['CVE-2024-0001', 'CVE-2023-9999'],
347
+ summary: 'New Vulnerability',
348
+ },
349
+ ],
350
+ },
351
+ ],
352
+ },
353
+ ],
354
+ }),
355
+ stderr: '',
356
+ exitCode: 1,
357
+ };
358
+ }
359
+ return { stdout: '', stderr: '', exitCode: 0 };
360
+ });
322
361
  mockHttpRepository.get.mockResolvedValue(
323
362
  JSON.stringify({
324
363
  vulnerabilities: [
@@ -354,22 +393,17 @@ describe('DailySecurityScanUseCase', () => {
354
393
 
355
394
  expect(mockHttpRepository.get.mock.calls).toHaveLength(1);
356
395
  expect(mockHttpRepository.get.mock.calls[0][0]).toBe(KEV_CATALOG_URL);
357
- expect(mockIssueRepository.createNewIssue.mock.calls).toHaveLength(1);
358
- expect(mockIssueRepository.createNewIssue.mock.calls[0][0]).toBe(
359
- 'example-org',
360
- );
361
- expect(mockIssueRepository.createNewIssue.mock.calls[0][1]).toBe(
362
- 'security-reports',
363
- );
364
- expect(mockIssueRepository.createNewIssue.mock.calls[0][2]).toBe(
396
+ const kevIssueCalls =
397
+ mockIssueRepository.createNewIssue.mock.calls.filter(
398
+ (call) => call[1] === 'security-reports',
399
+ );
400
+ expect(kevIssueCalls).toHaveLength(1);
401
+ expect(kevIssueCalls[0][0]).toBe('example-org');
402
+ expect(kevIssueCalls[0][2]).toBe(
365
403
  'CISA KEV new additions since 2024-01-01',
366
404
  );
367
- expect(mockIssueRepository.createNewIssue.mock.calls[0][3]).toContain(
368
- 'CVE-2024-0001',
369
- );
370
- expect(mockIssueRepository.createNewIssue.mock.calls[0][3]).not.toContain(
371
- 'CVE-2023-9999',
372
- );
405
+ expect(kevIssueCalls[0][3]).toContain('CVE-2024-0001');
406
+ expect(kevIssueCalls[0][3]).not.toContain('CVE-2023-9999');
373
407
  });
374
408
 
375
409
  it('does not create a KEV report issue when there are no new additions', async () => {
@@ -428,218 +462,6 @@ describe('DailySecurityScanUseCase', () => {
428
462
  expect(mockIssueRepository.createNewIssue.mock.calls).toHaveLength(0);
429
463
  });
430
464
 
431
- it('does not create a KEV report issue when the product is absent from the scanned workspace', async () => {
432
- const {
433
- useCase,
434
- mockLocalCommandRunner,
435
- mockIssueRepository,
436
- mockHttpRepository,
437
- } = buildUseCase();
438
-
439
- mockLocalCommandRunner.runCommand.mockImplementation(
440
- async (program, args) => {
441
- if (program === 'find' && args.includes('-maxdepth')) {
442
- return {
443
- stdout: '/repos/app/.git\n/repos/site/.git\n',
444
- stderr: '',
445
- exitCode: 0,
446
- };
447
- }
448
- if (program === 'git' && args.includes('grep')) {
449
- return { stdout: '', stderr: '', exitCode: 1 };
450
- }
451
- return { stdout: '', stderr: '', exitCode: 0 };
452
- },
453
- );
454
- mockHttpRepository.get.mockResolvedValue(
455
- JSON.stringify({
456
- vulnerabilities: [
457
- {
458
- cveID: 'CVE-2024-0001',
459
- vendorProject: 'Progress',
460
- product: 'LoadMaster',
461
- vulnerabilityName: 'Progress LoadMaster Command Injection',
462
- dateAdded: '2024-01-02',
463
- },
464
- ],
465
- }),
466
- );
467
-
468
- await useCase.run({
469
- targetDates: [new Date('2024-01-02T05:00:00Z')],
470
- org: 'example-org',
471
- manager: 'manager-name',
472
- dailySecurityScan: {
473
- scanBaseDirectory: '/repos',
474
- targetHourUtc: 5,
475
- enableKevNvdReport: true,
476
- kevReportRepo: 'security-reports',
477
- },
478
- });
479
-
480
- const gitGrepCalls = mockLocalCommandRunner.runCommand.mock.calls.filter(
481
- (call) => call[0] === 'git' && call[1].includes('grep'),
482
- );
483
- expect(gitGrepCalls.map((call) => call[1])).toEqual([
484
- [
485
- '-C',
486
- '/repos/app',
487
- 'grep',
488
- '-I',
489
- '-i',
490
- '-q',
491
- '-F',
492
- '-e',
493
- 'LoadMaster',
494
- ],
495
- [
496
- '-C',
497
- '/repos/site',
498
- 'grep',
499
- '-I',
500
- '-i',
501
- '-q',
502
- '-F',
503
- '-e',
504
- 'LoadMaster',
505
- ],
506
- ]);
507
- expect(mockIssueRepository.createNewIssue.mock.calls).toHaveLength(0);
508
- });
509
-
510
- it('reports only the new KEV entries whose product is present in the scanned workspace', async () => {
511
- const {
512
- useCase,
513
- mockLocalCommandRunner,
514
- mockIssueRepository,
515
- mockHttpRepository,
516
- } = buildUseCase();
517
-
518
- mockLocalCommandRunner.runCommand.mockImplementation(
519
- async (program, args) => {
520
- if (program === 'find' && args.includes('-maxdepth')) {
521
- return { stdout: '/repos/app/.git\n', stderr: '', exitCode: 0 };
522
- }
523
- if (program === 'git' && args.includes('grep')) {
524
- return {
525
- stdout: '',
526
- stderr: '',
527
- exitCode: args.includes('LoadMaster') ? 1 : 0,
528
- };
529
- }
530
- return { stdout: '', stderr: '', exitCode: 0 };
531
- },
532
- );
533
- mockHttpRepository.get.mockResolvedValue(
534
- JSON.stringify({
535
- vulnerabilities: [
536
- {
537
- cveID: 'CVE-2024-0001',
538
- vendorProject: 'Progress',
539
- product: 'LoadMaster',
540
- vulnerabilityName: 'Progress LoadMaster Command Injection',
541
- dateAdded: '2024-01-02',
542
- },
543
- {
544
- cveID: 'CVE-2024-0002',
545
- vendorProject: 'Example',
546
- product: 'ExampleLibrary',
547
- vulnerabilityName: 'Example Library Deserialization',
548
- dateAdded: '2024-01-02',
549
- },
550
- ],
551
- }),
552
- );
553
-
554
- await useCase.run({
555
- targetDates: [new Date('2024-01-02T05:00:00Z')],
556
- org: 'example-org',
557
- manager: 'manager-name',
558
- dailySecurityScan: {
559
- scanBaseDirectory: '/repos',
560
- targetHourUtc: 5,
561
- enableKevNvdReport: true,
562
- kevReportRepo: 'security-reports',
563
- },
564
- });
565
-
566
- expect(mockIssueRepository.createNewIssue.mock.calls).toHaveLength(1);
567
- expect(mockIssueRepository.createNewIssue.mock.calls[0][3]).toContain(
568
- 'CVE-2024-0002',
569
- );
570
- expect(mockIssueRepository.createNewIssue.mock.calls[0][3]).not.toContain(
571
- 'CVE-2024-0001',
572
- );
573
- });
574
-
575
- it('logs a failed repository search and keeps searching the remaining repositories', async () => {
576
- const {
577
- useCase,
578
- mockLocalCommandRunner,
579
- mockIssueRepository,
580
- mockHttpRepository,
581
- } = buildUseCase();
582
- const errorSpy = jest
583
- .spyOn(console, 'error')
584
- .mockImplementation(() => undefined);
585
-
586
- mockLocalCommandRunner.runCommand.mockImplementation(
587
- async (program, args) => {
588
- if (program === 'find' && args.includes('-maxdepth')) {
589
- return {
590
- stdout: '/repos/broken/.git\n/repos/app/.git\n',
591
- stderr: '',
592
- exitCode: 0,
593
- };
594
- }
595
- if (program === 'git' && args.includes('grep')) {
596
- return args.includes('/repos/broken')
597
- ? {
598
- stdout: '',
599
- stderr: 'fatal: not a git repository',
600
- exitCode: 128,
601
- }
602
- : { stdout: '', stderr: '', exitCode: 0 };
603
- }
604
- return { stdout: '', stderr: '', exitCode: 0 };
605
- },
606
- );
607
- mockHttpRepository.get.mockResolvedValue(
608
- JSON.stringify({
609
- vulnerabilities: [
610
- {
611
- cveID: 'CVE-2024-0001',
612
- vendorProject: 'Progress',
613
- product: 'LoadMaster',
614
- vulnerabilityName: 'Progress LoadMaster Command Injection',
615
- dateAdded: '2024-01-02',
616
- },
617
- ],
618
- }),
619
- );
620
-
621
- await useCase.run({
622
- targetDates: [new Date('2024-01-02T05:00:00Z')],
623
- org: 'example-org',
624
- manager: 'manager-name',
625
- dailySecurityScan: {
626
- scanBaseDirectory: '/repos',
627
- targetHourUtc: 5,
628
- enableKevNvdReport: true,
629
- kevReportRepo: 'security-reports',
630
- },
631
- });
632
-
633
- expect(errorSpy).toHaveBeenCalledWith(
634
- 'Failed to search /repos/broken for LoadMaster: fatal: not a git repository',
635
- );
636
- expect(mockIssueRepository.createNewIssue.mock.calls).toHaveLength(1);
637
- expect(mockIssueRepository.createNewIssue.mock.calls[0][3]).toContain(
638
- 'CVE-2024-0001',
639
- );
640
- errorSpy.mockRestore();
641
- });
642
-
643
465
  it('throws when the KEV catalog format is unexpected', async () => {
644
466
  const { useCase, mockLocalCommandRunner, mockHttpRepository } =
645
467
  buildUseCase();
@@ -741,15 +563,41 @@ describe('DailySecurityScanUseCase', () => {
741
563
  };
742
564
  }
743
565
  if (program === 'osv-scanner') {
744
- const dir = args[args.length - 1];
745
- if (dir.includes('broken')) {
566
+ const scannedDirectory = args[args.indexOf('-r') + 1];
567
+ if (scannedDirectory.includes('broken')) {
746
568
  return {
747
569
  stdout: '',
748
570
  stderr: 'osv-scanner: command not found',
749
571
  exitCode: 127,
750
572
  };
751
573
  }
752
- return { stdout: 'vulnerability found', stderr: '', exitCode: 1 };
574
+ return {
575
+ stdout: JSON.stringify({
576
+ results: [
577
+ {
578
+ source: { path: scannedDirectory, type: 'lockfile' },
579
+ packages: [
580
+ {
581
+ package: {
582
+ name: 'example-library',
583
+ version: '1.2.3',
584
+ ecosystem: 'npm',
585
+ },
586
+ vulnerabilities: [
587
+ {
588
+ id: 'GHSA-1111-2222-3333',
589
+ aliases: [],
590
+ summary: 'Example Library Deserialization',
591
+ },
592
+ ],
593
+ },
594
+ ],
595
+ },
596
+ ],
597
+ }),
598
+ stderr: '',
599
+ exitCode: 1,
600
+ };
753
601
  }
754
602
  return { stdout: '', stderr: '', exitCode: 0 };
755
603
  },
@@ -869,5 +717,219 @@ describe('DailySecurityScanUseCase', () => {
869
717
  );
870
718
  expect(mockIssueRepository.createCommentByUrl.mock.calls).toHaveLength(0);
871
719
  });
720
+
721
+ const osvScanOutput = (
722
+ vulnerablePackages: {
723
+ name: string;
724
+ version: string;
725
+ ecosystem: string;
726
+ id: string;
727
+ aliases: string[];
728
+ summary: string;
729
+ }[],
730
+ ): string =>
731
+ JSON.stringify({
732
+ results: [
733
+ {
734
+ source: { path: '/repos/example-org/app', type: 'lockfile' },
735
+ packages: vulnerablePackages.map((vulnerablePackage) => ({
736
+ package: {
737
+ name: vulnerablePackage.name,
738
+ version: vulnerablePackage.version,
739
+ ecosystem: vulnerablePackage.ecosystem,
740
+ },
741
+ vulnerabilities: [
742
+ {
743
+ id: vulnerablePackage.id,
744
+ aliases: vulnerablePackage.aliases,
745
+ summary: vulnerablePackage.summary,
746
+ },
747
+ ],
748
+ })),
749
+ },
750
+ ],
751
+ });
752
+
753
+ const buildScanEnvironment = (scanOutput: string, kevCatalog: unknown) => {
754
+ const built = buildUseCase();
755
+ built.mockIssueRepository.searchIssue.mockResolvedValue([]);
756
+ built.mockLocalCommandRunner.runCommand.mockImplementation(
757
+ async (program) => {
758
+ if (program === 'find') {
759
+ return {
760
+ stdout: '/repos/example-org/app/.git\n',
761
+ stderr: '',
762
+ exitCode: 0,
763
+ };
764
+ }
765
+ if (program === 'git') {
766
+ return {
767
+ stdout: 'git@github.com:example-org/app.git\n',
768
+ stderr: '',
769
+ exitCode: 0,
770
+ };
771
+ }
772
+ if (program === 'osv-scanner') {
773
+ return { stdout: scanOutput, stderr: '', exitCode: 1 };
774
+ }
775
+ return { stdout: '', stderr: '', exitCode: 0 };
776
+ },
777
+ );
778
+ built.mockHttpRepository.get.mockResolvedValue(
779
+ JSON.stringify(kevCatalog),
780
+ );
781
+ return built;
782
+ };
783
+
784
+ const kevReportCalls = (
785
+ calls: [string, string, string, string, string[], string[]][],
786
+ ) => calls.filter((call) => call[1] === 'security-reports');
787
+
788
+ const runWithKevReporting = async (useCase: DailySecurityScanUseCase) =>
789
+ useCase.run({
790
+ targetDates: [new Date('2024-01-02T05:00:00Z')],
791
+ org: 'example-org',
792
+ manager: 'manager-name',
793
+ dailySecurityScan: {
794
+ scanBaseDirectory: '/repos',
795
+ targetHourUtc: 5,
796
+ enableKevNvdReport: true,
797
+ kevReportRepo: 'security-reports',
798
+ },
799
+ });
800
+
801
+ it('reports a KEV addition whose CVE the scanner found at an installed version', async () => {
802
+ const { useCase, mockIssueRepository } = buildScanEnvironment(
803
+ osvScanOutput([
804
+ {
805
+ name: 'example-library',
806
+ version: '1.2.3',
807
+ ecosystem: 'npm',
808
+ id: 'GHSA-1111-2222-3333',
809
+ aliases: ['CVE-2024-0001'],
810
+ summary: 'Example Library Deserialization',
811
+ },
812
+ ]),
813
+ {
814
+ vulnerabilities: [
815
+ {
816
+ cveID: 'CVE-2024-0001',
817
+ vendorProject: 'Example',
818
+ product: 'ExampleLibrary',
819
+ vulnerabilityName: 'Example Library Deserialization',
820
+ dateAdded: '2024-01-02',
821
+ },
822
+ ],
823
+ },
824
+ );
825
+
826
+ await runWithKevReporting(useCase);
827
+
828
+ const kevCalls = kevReportCalls(
829
+ mockIssueRepository.createNewIssue.mock.calls,
830
+ );
831
+ expect(kevCalls).toHaveLength(1);
832
+ expect(kevCalls[0][3]).toContain('CVE-2024-0001');
833
+ expect(kevCalls[0][3]).toContain('app');
834
+ expect(kevCalls[0][3]).toContain('example-library');
835
+ expect(kevCalls[0][3]).toContain('1.2.3');
836
+ });
837
+
838
+ it('does not report a KEV addition that the scanner did not find in any repository', async () => {
839
+ const { useCase, mockIssueRepository } = buildScanEnvironment(
840
+ osvScanOutput([
841
+ {
842
+ name: 'example-library',
843
+ version: '1.2.3',
844
+ ecosystem: 'npm',
845
+ id: 'GHSA-1111-2222-3333',
846
+ aliases: ['CVE-2024-0001'],
847
+ summary: 'Example Library Deserialization',
848
+ },
849
+ ]),
850
+ {
851
+ vulnerabilities: [
852
+ {
853
+ cveID: 'CVE-2024-9999',
854
+ vendorProject: 'Progress',
855
+ product: 'LoadMaster',
856
+ vulnerabilityName: 'Progress LoadMaster Command Injection',
857
+ dateAdded: '2024-01-02',
858
+ },
859
+ ],
860
+ },
861
+ );
862
+
863
+ await runWithKevReporting(useCase);
864
+
865
+ expect(
866
+ kevReportCalls(mockIssueRepository.createNewIssue.mock.calls),
867
+ ).toHaveLength(0);
868
+ });
869
+
870
+ it('reports a KEV addition whose CVE the scanner returned as the vulnerability id rather than an alias', async () => {
871
+ const { useCase, mockIssueRepository } = buildScanEnvironment(
872
+ osvScanOutput([
873
+ {
874
+ name: 'example-library',
875
+ version: '1.2.3',
876
+ ecosystem: 'npm',
877
+ id: 'CVE-2024-0001',
878
+ aliases: [],
879
+ summary: 'Example Library Deserialization',
880
+ },
881
+ ]),
882
+ {
883
+ vulnerabilities: [
884
+ {
885
+ cveID: 'CVE-2024-0001',
886
+ vendorProject: 'Example',
887
+ product: 'ExampleLibrary',
888
+ vulnerabilityName: 'Example Library Deserialization',
889
+ dateAdded: '2024-01-02',
890
+ },
891
+ ],
892
+ },
893
+ );
894
+
895
+ await runWithKevReporting(useCase);
896
+
897
+ expect(
898
+ kevReportCalls(mockIssueRepository.createNewIssue.mock.calls),
899
+ ).toHaveLength(1);
900
+ });
901
+
902
+ it('does not search the repositories for the KEV product name', async () => {
903
+ const { useCase, mockLocalCommandRunner } = buildScanEnvironment(
904
+ osvScanOutput([
905
+ {
906
+ name: 'example-library',
907
+ version: '1.2.3',
908
+ ecosystem: 'npm',
909
+ id: 'GHSA-1111-2222-3333',
910
+ aliases: ['CVE-2024-0001'],
911
+ summary: 'Example Library Deserialization',
912
+ },
913
+ ]),
914
+ {
915
+ vulnerabilities: [
916
+ {
917
+ cveID: 'CVE-2024-0001',
918
+ vendorProject: 'Example',
919
+ product: 'ExampleLibrary',
920
+ vulnerabilityName: 'Example Library Deserialization',
921
+ dateAdded: '2024-01-02',
922
+ },
923
+ ],
924
+ },
925
+ );
926
+
927
+ await runWithKevReporting(useCase);
928
+
929
+ const grepCalls = mockLocalCommandRunner.runCommand.mock.calls.filter(
930
+ (call) => call[0] === 'git' && call[1].includes('grep'),
931
+ );
932
+ expect(grepCalls).toHaveLength(0);
933
+ });
872
934
  });
873
935
  });
@@ -47,6 +47,78 @@ const isKevCatalog = (value: unknown): value is KevCatalog => {
47
47
  );
48
48
  };
49
49
 
50
+ type ScannedVulnerablePackage = {
51
+ repositoryName: string;
52
+ ecosystem: string;
53
+ packageName: string;
54
+ packageVersion: string;
55
+ vulnerabilityId: string;
56
+ vulnerabilityIdentifiers: string[];
57
+ summary: string;
58
+ };
59
+
60
+ const parseScannerVulnerabilities = (
61
+ repositoryName: string,
62
+ scannerOutput: string,
63
+ ): ScannedVulnerablePackage[] => {
64
+ let parsed: unknown;
65
+ try {
66
+ parsed = JSON.parse(scannerOutput);
67
+ } catch (error) {
68
+ console.error(
69
+ `Unparsable osv-scanner output for ${repositoryName}: ${String(error)}`,
70
+ );
71
+ return [];
72
+ }
73
+ const toRecord = (value: unknown): Record<string, unknown> =>
74
+ typeof value === 'object' && value !== null ? { ...value } : {};
75
+ const readArray = (value: unknown, key: string): unknown[] => {
76
+ const entry = toRecord(value)[key];
77
+ return Array.isArray(entry) ? entry : [];
78
+ };
79
+ const readString = (value: unknown, key: string): string => {
80
+ const entry = toRecord(value)[key];
81
+ return typeof entry === 'string' ? entry : '';
82
+ };
83
+ return readArray(parsed, 'results').flatMap((result) =>
84
+ readArray(result, 'packages').flatMap((scannedPackage) => {
85
+ const packageDetail = toRecord(scannedPackage).package;
86
+ return readArray(scannedPackage, 'vulnerabilities').map(
87
+ (vulnerability) => {
88
+ const vulnerabilityId = readString(vulnerability, 'id');
89
+ const aliases = readArray(vulnerability, 'aliases').filter(
90
+ (alias): alias is string => typeof alias === 'string',
91
+ );
92
+ return {
93
+ repositoryName,
94
+ ecosystem: readString(packageDetail, 'ecosystem'),
95
+ packageName: readString(packageDetail, 'name'),
96
+ packageVersion: readString(packageDetail, 'version'),
97
+ vulnerabilityId,
98
+ vulnerabilityIdentifiers: [vulnerabilityId, ...aliases],
99
+ summary: readString(vulnerability, 'summary'),
100
+ };
101
+ },
102
+ );
103
+ }),
104
+ );
105
+ };
106
+
107
+ const renderScannerFindings = (
108
+ today: string,
109
+ vulnerablePackages: ScannedVulnerablePackage[],
110
+ ): string =>
111
+ [
112
+ '## OSV-Scanner findings',
113
+ '',
114
+ `### ${today}`,
115
+ '',
116
+ ...vulnerablePackages.map(
117
+ (vulnerablePackage) =>
118
+ `- ${vulnerablePackage.ecosystem} ${vulnerablePackage.packageName} ${vulnerablePackage.packageVersion} ${vulnerablePackage.vulnerabilityIdentifiers.join(' ')} ${vulnerablePackage.summary}`,
119
+ ),
120
+ ].join('\n');
121
+
50
122
  const KEV_CATALOG_URL =
51
123
  'https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json';
52
124
 
@@ -78,7 +150,7 @@ export class DailySecurityScanUseCase {
78
150
  const lastTargetDate = input.targetDates[input.targetDates.length - 1];
79
151
  const today = lastTargetDate.toISOString().slice(0, 10);
80
152
 
81
- await this.scanRepositories(
153
+ const scannedVulnerablePackages = await this.scanRepositories(
82
154
  input.org,
83
155
  input.manager,
84
156
  today,
@@ -90,6 +162,7 @@ export class DailySecurityScanUseCase {
90
162
  input.manager,
91
163
  lastTargetDate,
92
164
  input.dailySecurityScan,
165
+ scannedVulnerablePackages,
93
166
  );
94
167
  };
95
168
 
@@ -98,7 +171,7 @@ export class DailySecurityScanUseCase {
98
171
  manager: Member['name'],
99
172
  today: string,
100
173
  config: DailySecurityScanConfig,
101
- ): Promise<void> => {
174
+ ): Promise<ScannedVulnerablePackage[]> => {
102
175
  const { stdout: findOutput } = await this.localCommandRunner.runCommand(
103
176
  'find',
104
177
  [
@@ -121,9 +194,10 @@ export class DailySecurityScanUseCase {
121
194
  console.error(
122
195
  `No repositories found in scan base directory: ${config.scanBaseDirectory}`,
123
196
  );
124
- return;
197
+ return [];
125
198
  }
126
199
 
200
+ const scannedVulnerablePackages: ScannedVulnerablePackage[] = [];
127
201
  for (const repositoryDirectory of repositoryDirectories) {
128
202
  const { stdout: remoteUrl, exitCode: remoteExitCode } =
129
203
  await this.localCommandRunner.runCommand('git', [
@@ -155,6 +229,8 @@ export class DailySecurityScanUseCase {
155
229
  'source',
156
230
  '-r',
157
231
  repositoryDirectory,
232
+ '--format',
233
+ 'json',
158
234
  ]);
159
235
  if (scanExitCode === 0) {
160
236
  continue;
@@ -166,7 +242,13 @@ export class DailySecurityScanUseCase {
166
242
  continue;
167
243
  }
168
244
 
169
- const findingsBody = `## OSV-Scanner findings\n\n### ${today}\n\n\`\`\`\n${scanOutput}\n\`\`\``;
245
+ const vulnerablePackages = parseScannerVulnerabilities(
246
+ repositoryName,
247
+ scanOutput,
248
+ );
249
+ scannedVulnerablePackages.push(...vulnerablePackages);
250
+
251
+ const findingsBody = renderScannerFindings(today, vulnerablePackages);
170
252
  const existingIssues = await this.issueRepository.searchIssue({
171
253
  owner: repositoryOrg,
172
254
  repositoryName,
@@ -193,6 +275,7 @@ export class DailySecurityScanUseCase {
193
275
  );
194
276
  }
195
277
  }
278
+ return scannedVulnerablePackages;
196
279
  };
197
280
 
198
281
  private reportKevAdditions = async (
@@ -200,6 +283,7 @@ export class DailySecurityScanUseCase {
200
283
  manager: Member['name'],
201
284
  lastTargetDate: Date,
202
285
  config: DailySecurityScanConfig,
286
+ scannedVulnerablePackages: ScannedVulnerablePackage[],
203
287
  ): Promise<void> => {
204
288
  if (!config.enableKevNvdReport || !config.kevReportRepo) {
205
289
  return;
@@ -220,18 +304,15 @@ export class DailySecurityScanUseCase {
220
304
  const newKevEntries = parsedKev.vulnerabilities.filter(
221
305
  (vulnerability) => vulnerability.dateAdded >= yesterdayYmd,
222
306
  );
223
- const usedKevEntries: KevVulnerability[] = [];
224
- for (const vulnerability of newKevEntries) {
225
- if (
226
- await this.isProductPresentInScannedWorkspace(
227
- config.scanBaseDirectory,
228
- vulnerability.product,
229
- )
230
- ) {
231
- usedKevEntries.push(vulnerability);
232
- }
233
- }
234
- if (usedKevEntries.length === 0) {
307
+ const affectingKevEntries = newKevEntries
308
+ .map((vulnerability) => ({
309
+ vulnerability,
310
+ affectedPackages: scannedVulnerablePackages.filter((scannedPackage) =>
311
+ scannedPackage.vulnerabilityIdentifiers.includes(vulnerability.cveID),
312
+ ),
313
+ }))
314
+ .filter((entry) => entry.affectedPackages.length > 0);
315
+ if (affectingKevEntries.length === 0) {
235
316
  return;
236
317
  }
237
318
 
@@ -239,54 +320,19 @@ export class DailySecurityScanUseCase {
239
320
  org,
240
321
  config.kevReportRepo,
241
322
  `CISA KEV new additions since ${yesterdayYmd}`,
242
- usedKevEntries
243
- .map(
244
- (vulnerability) =>
245
- `- ${vulnerability.dateAdded} ${vulnerability.cveID} ${vulnerability.vulnerabilityName}`,
323
+ affectingKevEntries
324
+ .map((entry) =>
325
+ [
326
+ `- ${entry.vulnerability.dateAdded} ${entry.vulnerability.cveID} ${entry.vulnerability.vulnerabilityName}`,
327
+ ...entry.affectedPackages.map(
328
+ (affectedPackage) =>
329
+ ` - ${affectedPackage.repositoryName} ${affectedPackage.ecosystem} ${affectedPackage.packageName} ${affectedPackage.packageVersion}`,
330
+ ),
331
+ ].join('\n'),
246
332
  )
247
333
  .join('\n'),
248
334
  [manager],
249
335
  [],
250
336
  );
251
337
  };
252
-
253
- private isProductPresentInScannedWorkspace = async (
254
- scanBaseDirectory: string,
255
- product: string,
256
- ): Promise<boolean> => {
257
- const { stdout: findOutput } = await this.localCommandRunner.runCommand(
258
- 'find',
259
- [scanBaseDirectory, '-maxdepth', '3', '-name', '.git', '-type', 'd'],
260
- );
261
- const repositoryDirectories = findOutput
262
- .split('\n')
263
- .filter((line) => line.length > 0)
264
- .map((gitDirectory) => gitDirectory.replace(/\/\.git$/, ''));
265
-
266
- for (const repositoryDirectory of repositoryDirectories) {
267
- const { stderr, exitCode } = await this.localCommandRunner.runCommand(
268
- 'git',
269
- [
270
- '-C',
271
- repositoryDirectory,
272
- 'grep',
273
- '-I',
274
- '-i',
275
- '-q',
276
- '-F',
277
- '-e',
278
- product,
279
- ],
280
- );
281
- if (exitCode === 0) {
282
- return true;
283
- }
284
- if (exitCode !== 1) {
285
- console.error(
286
- `Failed to search ${repositoryDirectory} for ${product}: ${stderr}`,
287
- );
288
- }
289
- }
290
- return false;
291
- };
292
338
  }
@@ -21,6 +21,5 @@ export declare class DailySecurityScanUseCase {
21
21
  }) => Promise<void>;
22
22
  private scanRepositories;
23
23
  private reportKevAdditions;
24
- private isProductPresentInScannedWorkspace;
25
24
  }
26
25
  //# sourceMappingURL=DailySecurityScanUseCase.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DailySecurityScanUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/DailySecurityScanUseCase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AACrE,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,MAAM,uBAAuB,GAAG;IACpC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AA0CF,qBAAa,wBAAwB;IAEjC,QAAQ,CAAC,kBAAkB,EAAE,kBAAkB;IAC/C,QAAQ,CAAC,eAAe,EAAE,IAAI,CAC5B,eAAe,EACf,gBAAgB,GAAG,aAAa,GAAG,oBAAoB,CACxD;IACD,QAAQ,CAAC,cAAc,EAAE,cAAc;gBAL9B,kBAAkB,EAAE,kBAAkB,EACtC,eAAe,EAAE,IAAI,CAC5B,eAAe,EACf,gBAAgB,GAAG,aAAa,GAAG,oBAAoB,CACxD,EACQ,cAAc,EAAE,cAAc;IAGzC,GAAG,GAAU,OAAO;QAClB,WAAW,EAAE,IAAI,EAAE,CAAC;QACpB,GAAG,EAAE,MAAM,CAAC;QACZ,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QACxB,iBAAiB,EAAE,uBAAuB,CAAC;KAC5C,KAAG,OAAO,CAAC,IAAI,CAAC,CA0Bf;IAEF,OAAO,CAAC,gBAAgB,CAoGtB;IAEF,OAAO,CAAC,kBAAkB,CAqDxB;IAEF,OAAO,CAAC,kCAAkC,CAsCxC;CACH"}
1
+ {"version":3,"file":"DailySecurityScanUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/DailySecurityScanUseCase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AACrE,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,MAAM,uBAAuB,GAAG;IACpC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAkHF,qBAAa,wBAAwB;IAEjC,QAAQ,CAAC,kBAAkB,EAAE,kBAAkB;IAC/C,QAAQ,CAAC,eAAe,EAAE,IAAI,CAC5B,eAAe,EACf,gBAAgB,GAAG,aAAa,GAAG,oBAAoB,CACxD;IACD,QAAQ,CAAC,cAAc,EAAE,cAAc;gBAL9B,kBAAkB,EAAE,kBAAkB,EACtC,eAAe,EAAE,IAAI,CAC5B,eAAe,EACf,gBAAgB,GAAG,aAAa,GAAG,oBAAoB,CACxD,EACQ,cAAc,EAAE,cAAc;IAGzC,GAAG,GAAU,OAAO;QAClB,WAAW,EAAE,IAAI,EAAE,CAAC;QACpB,GAAG,EAAE,MAAM,CAAC;QACZ,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QACxB,iBAAiB,EAAE,uBAAuB,CAAC;KAC5C,KAAG,OAAO,CAAC,IAAI,CAAC,CA2Bf;IAEF,OAAO,CAAC,gBAAgB,CA8GtB;IAEF,OAAO,CAAC,kBAAkB,CAwDxB;CACH"}