Skip to content

Commit

Permalink
SecurityAdvisories: skip duplicate GitHub advisories where package na…
Browse files Browse the repository at this point in the history
…me and CVE matches (#1452)
  • Loading branch information
glaubinix committed May 17, 2024
1 parent f383524 commit 9ae85d8
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 0 deletions.
11 changes: 11 additions & 0 deletions src/SecurityAdvisory/GitHubSecurityAdvisoriesSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ public function getAdvisories(ConsoleIO $io): ?RemoteSecurityAdvisoryCollection
{
/** @var array<string, array<string, RemoteSecurityAdvisory>> $advisoryMap */
$advisoryMap = [];
/** @var array<string, array<string, true>> $foundPackageCves */
$foundPackageCves = [];
$hasNextPage = true;
$after = '';

Expand Down Expand Up @@ -102,6 +104,15 @@ public function getAdvisories(ConsoleIO $io): ?RemoteSecurityAdvisoryCollection
continue;
}

// GitHub can have multiple advisories per CVE and package
if ($cve !== null) {
if (isset($foundPackageCves[$packageName][$cve])) {
continue;
}

$foundPackageCves[$packageName][$cve] = true;
}

$references = [];
foreach ($node['advisory']['references'] as $reference) {
if (isset($reference['url'])) {
Expand Down
50 changes: 50 additions & 0 deletions tests/SecurityAdvisory/GitHubSecurityAdvisoriesSourceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,38 @@ public function testWithPagination(): void
$this->assertSame(Severity::MEDIUM, $advisories[1]->severity);
}

public function testDuplicateCvePerPackage(): void
{
$responseFactory = function (string $method, string $url, array $options) {
$this->assertSame('POST', $method);
$this->assertSame('https://api.github.com/graphql', $url);
$this->assertSame('{"query":"query{securityVulnerabilities(ecosystem:COMPOSER,first:100){nodes{advisory{summary,permalink,publishedAt,withdrawnAt,severity,identifiers{type,value},references{url}},vulnerableVersionRange,package{name}},pageInfo{hasNextPage,endCursor}}}"}', $options['body']);

return new MockResponse(json_encode($this->getGraphQLResultPageWithMultipleCvePerPackage()), ['http_code' => 200, 'response_headers' => ['Content-Type' => 'application/json; charset=utf-8']]);
};
$client = new MockHttpClient($responseFactory);

$source = new GitHubSecurityAdvisoriesSource($client, new NullLogger(), $this->providerManager, [], $this->doctrine);
$package = $this->getPackage();
$advisoryCollection = $source->getAdvisories(new BufferIO());

$this->assertNotNull($advisoryCollection);
$this->assertSame(1, $client->getRequestsCount());

$advisories = $advisoryCollection->getAdvisoriesForPackageName($package->getName());
$this->assertCount(1, $advisories);

$this->assertSame('GHSA-h58v-c6rf-abcd', $advisories[0]->id);
$this->assertSame('Insert tag injection', $advisories[0]->title);
$this->assertSame('vendor/package', $advisories[0]->packageName);
$this->assertSame('=4.10.0', $advisories[0]->affectedVersions);
$this->assertSame('https://github.com/advisories/GHSA-h58v-c6rf-abcd', $advisories[0]->link);
$this->assertSame('CVE-2020-25768', $advisories[0]->cve);
$this->assertSame('2021-07-01T17:00:04+0000', $advisories[0]->date->format(\DateTimeInterface::ISO8601));
$this->assertNull($advisories[0]->composerRepository);
$this->assertSame(Severity::MEDIUM, $advisories[0]->severity);
}

private function getPackage(): Package
{
$package = new Package();
Expand Down Expand Up @@ -191,6 +223,24 @@ private function getGraphQLResultSecondPage(): array
];
}

private function getGraphQLResultPageWithMultipleCvePerPackage(): array
{
return [
'data' => [
'securityVulnerabilities' => [
'nodes' => [
$this->graphQlPackageNode('GHSA-h58v-c6rf-abcd', 'vendor/package', '= 4.10.0', 'CVE-2020-25768', 'Insert tag injection', '2021-07-01T17:00:04Z'),
$this->graphQlPackageNode('GHSA-f7wm-x4gw-abcd', 'vendor/package', '= 4.10.0', 'CVE-2020-25768', 'Insert tag injection in forms', '2020-09-24T16:23:54Z'),
],
'pageInfo' => [
'hasNextPage' => false,
'endCursor' => 'Y3Vyc29yOnYyOpK5MjAxOS0xMi0xN1QyMDozNTozMSswMTowMM0LWQ==',
],
],
],
];
}

private function graphQlPackageNode(string $advisoryId, string $packageName, string $range, string $cve, string $summary, string $publishedAt): array
{
return [
Expand Down

0 comments on commit 9ae85d8

Please sign in to comment.