diff --git a/src/Composer/Advisory/Auditor.php b/src/Composer/Advisory/Auditor.php index 6ca3d8102..bc6520d55 100644 --- a/src/Composer/Advisory/Auditor.php +++ b/src/Composer/Advisory/Auditor.php @@ -247,6 +247,7 @@ class Auditor foreach ($packageAdvisories as $advisory) { $headers = [ 'Package', + 'Severity', 'CVE', 'Title', 'URL', @@ -255,6 +256,7 @@ class Auditor ]; $row = [ $advisory->packageName, + $this->getSeverity($advisory), $this->getCVE($advisory), $advisory->title, $this->getURL($advisory), @@ -289,6 +291,7 @@ class Auditor $error[] = '--------'; } $error[] = "Package: ".$advisory->packageName; + $error[] = "Severity: ".$this->getSeverity($advisory); $error[] = "CVE: ".$this->getCVE($advisory); $error[] = "Title: ".OutputFormatter::escape($advisory->title); $error[] = "URL: ".$this->getURL($advisory); @@ -350,6 +353,15 @@ class Auditor return $packageUrl !== null ? '' . $package->getPrettyName() . '' : $package->getPrettyName(); } + private function getSeverity(SecurityAdvisory $advisory): string + { + if ($advisory->severity === null) { + return ''; + } + + return $advisory->severity; + } + private function getCVE(SecurityAdvisory $advisory): string { if ($advisory->cve === null) { diff --git a/src/Composer/Advisory/IgnoredSecurityAdvisory.php b/src/Composer/Advisory/IgnoredSecurityAdvisory.php index ba9079287..3d8b56a1c 100644 --- a/src/Composer/Advisory/IgnoredSecurityAdvisory.php +++ b/src/Composer/Advisory/IgnoredSecurityAdvisory.php @@ -26,9 +26,9 @@ class IgnoredSecurityAdvisory extends SecurityAdvisory /** * @param non-empty-array $sources */ - public function __construct(string $packageName, string $advisoryId, ConstraintInterface $affectedVersions, string $title, array $sources, DateTimeImmutable $reportedAt, ?string $cve = null, ?string $link = null, ?string $ignoreReason = null) + public function __construct(string $packageName, string $advisoryId, ConstraintInterface $affectedVersions, string $title, array $sources, DateTimeImmutable $reportedAt, ?string $cve = null, ?string $link = null, ?string $ignoreReason = null, ?string $severity = null) { - parent::__construct($packageName, $advisoryId, $affectedVersions, $title, $sources, $reportedAt, $cve, $link); + parent::__construct($packageName, $advisoryId, $affectedVersions, $title, $sources, $reportedAt, $cve, $link, $severity); $this->ignoreReason = $ignoreReason; } diff --git a/src/Composer/Advisory/PartialSecurityAdvisory.php b/src/Composer/Advisory/PartialSecurityAdvisory.php index 28dbdc4f4..2867e9b60 100644 --- a/src/Composer/Advisory/PartialSecurityAdvisory.php +++ b/src/Composer/Advisory/PartialSecurityAdvisory.php @@ -44,7 +44,7 @@ class PartialSecurityAdvisory implements JsonSerializable { $constraint = $parser->parseConstraints($data['affectedVersions']); if (isset($data['title'], $data['sources'], $data['reportedAt'])) { - return new SecurityAdvisory($packageName, $data['advisoryId'], $constraint, $data['title'], $data['sources'], new \DateTimeImmutable($data['reportedAt'], new \DateTimeZone('UTC')), $data['cve'] ?? null, $data['link'] ?? null); + return new SecurityAdvisory($packageName, $data['advisoryId'], $constraint, $data['title'], $data['sources'], new \DateTimeImmutable($data['reportedAt'], new \DateTimeZone('UTC')), $data['cve'] ?? null, $data['link'] ?? null, $data['severity'] ?? null); } return new self($packageName, $data['advisoryId'], $constraint); diff --git a/src/Composer/Advisory/SecurityAdvisory.php b/src/Composer/Advisory/SecurityAdvisory.php index e88228d60..a3d58b462 100644 --- a/src/Composer/Advisory/SecurityAdvisory.php +++ b/src/Composer/Advisory/SecurityAdvisory.php @@ -47,10 +47,16 @@ class SecurityAdvisory extends PartialSecurityAdvisory */ public $sources; + /** + * @var string|null + * @readonly + */ + public $severity; + /** * @param non-empty-array $sources */ - public function __construct(string $packageName, string $advisoryId, ConstraintInterface $affectedVersions, string $title, array $sources, DateTimeImmutable $reportedAt, ?string $cve = null, ?string $link = null) + public function __construct(string $packageName, string $advisoryId, ConstraintInterface $affectedVersions, string $title, array $sources, DateTimeImmutable $reportedAt, ?string $cve = null, ?string $link = null, ?string $severity = null) { parent::__construct($packageName, $advisoryId, $affectedVersions); @@ -59,6 +65,7 @@ class SecurityAdvisory extends PartialSecurityAdvisory $this->reportedAt = $reportedAt; $this->cve = $cve; $this->link = $link; + $this->severity = $severity; } /** @@ -75,7 +82,8 @@ class SecurityAdvisory extends PartialSecurityAdvisory $this->reportedAt, $this->cve, $this->link, - $ignoreReason + $ignoreReason, + $this->severity ); } diff --git a/tests/Composer/Test/Advisory/AuditorTest.php b/tests/Composer/Test/Advisory/AuditorTest.php index 656505844..2253169f4 100644 --- a/tests/Composer/Test/Advisory/AuditorTest.php +++ b/tests/Composer/Test/Advisory/AuditorTest.php @@ -54,6 +54,7 @@ class AuditorTest extends TestCase 'expected' => 1, 'output' => 'Found 2 security vulnerability advisories affecting 1 package: Package: vendor1/package1 +Severity: high CVE: CVE3 Title: advisory4 URL: https://advisory.example.com/advisory4 @@ -61,6 +62,7 @@ Affected versions: >=8,<8.2.2|>=1,<2.5.6 Reported at: 2022-05-25T13:21:00+00:00 -------- Package: vendor1/package1 +Severity: medium CVE: '.' Title: advisory5 URL: https://advisory.example.com/advisory5 @@ -169,6 +171,7 @@ Found 2 abandoned packages: [ ['text' => 'Found 1 ignored security vulnerability advisory affecting 1 package:'], ['text' => 'Package: vendor1/package1'], + ['text' => 'Severity: medium'], ['text' => 'CVE: CVE1'], ['text' => 'Title: advisory1'], ['text' => 'URL: https://advisory.example.com/advisory1'], @@ -185,6 +188,7 @@ Found 2 abandoned packages: [ ['text' => 'Found 1 ignored security vulnerability advisory affecting 1 package:'], ['text' => 'Package: vendor1/package1'], + ['text' => 'Severity: medium'], ['text' => 'CVE: CVE1'], ['text' => 'Title: advisory1'], ['text' => 'URL: https://advisory.example.com/advisory1'], @@ -202,6 +206,7 @@ Found 2 abandoned packages: [ ['text' => 'Found 1 ignored security vulnerability advisory affecting 1 package:'], ['text' => 'Package: vendor1/package2'], + ['text' => 'Severity: medium'], ['text' => 'CVE: '], ['text' => 'Title: advisory2'], ['text' => 'URL: https://advisory.example.com/advisory2'], @@ -218,6 +223,7 @@ Found 2 abandoned packages: [ ['text' => 'Found 1 ignored security vulnerability advisory affecting 1 package:'], ['text' => 'Package: vendorx/packagex'], + ['text' => 'Severity: medium'], ['text' => 'CVE: CVE5'], ['text' => 'Title: advisory17'], ['text' => 'URL: https://advisory.example.com/advisory17'], @@ -234,6 +240,7 @@ Found 2 abandoned packages: [ ['text' => 'Found 1 security vulnerability advisory affecting 1 package:'], ['text' => 'Package: vendor1/package1'], + ['text' => 'Severity: medium'], ['text' => 'CVE: CVE1'], ['text' => 'Title: advisory1'], ['text' => 'URL: https://advisory.example.com/advisory1'], @@ -254,6 +261,7 @@ Found 2 abandoned packages: [ ['text' => 'Found 3 ignored security vulnerability advisories affecting 2 packages:'], ['text' => 'Package: vendor2/package1'], + ['text' => 'Severity: medium'], ['text' => 'CVE: CVE2'], ['text' => 'Title: advisory3'], ['text' => 'URL: https://advisory.example.com/advisory3'], @@ -262,6 +270,7 @@ Found 2 abandoned packages: ['text' => 'Ignore reason: None specified'], ['text' => '--------'], ['text' => 'Package: vendor2/package1'], + ['text' => 'Severity: medium'], ['text' => 'CVE: CVE4'], ['text' => 'Title: advisory6'], ['text' => 'URL: https://advisory.example.com/advisory6'], @@ -270,6 +279,7 @@ Found 2 abandoned packages: ['text' => 'Ignore reason: None specified'], ['text' => '--------'], ['text' => 'Package: vendorx/packagex'], + ['text' => 'Severity: medium'], ['text' => 'CVE: CVE5'], ['text' => 'Title: advisory17'], ['text' => 'URL: https://advisory.example.com/advisory17'], @@ -278,6 +288,7 @@ Found 2 abandoned packages: ['text' => 'Ignore reason: None specified'], ['text' => 'Found 1 security vulnerability advisory affecting 1 package:'], ['text' => 'Package: vendor3/package1'], + ['text' => 'Severity: medium'], ['text' => 'CVE: CVE5'], ['text' => 'Title: advisory7'], ['text' => 'URL: https://advisory.example.com/advisory7'], @@ -380,6 +391,7 @@ Found 2 abandoned packages: ], 'reportedAt' => '2022-05-25 13:21:00', 'composerRepository' => 'https://packagist.org', + 'severity' => 'medium', ], [ 'advisoryId' => 'ID4', @@ -396,6 +408,7 @@ Found 2 abandoned packages: ], 'reportedAt' => '2022-05-25 13:21:00', 'composerRepository' => 'https://packagist.org', + 'severity' => 'high', ], [ 'advisoryId' => 'ID5', @@ -412,6 +425,7 @@ Found 2 abandoned packages: ], 'reportedAt' => '2022-05-25 13:21:00', 'composerRepository' => 'https://packagist.org', + 'severity' => 'medium', ], ], 'vendor1/package2' => [ @@ -430,6 +444,7 @@ Found 2 abandoned packages: ], 'reportedAt' => '2022-05-25 13:21:00', 'composerRepository' => 'https://packagist.org', + 'severity' => 'medium', ], ], 'vendorx/packagex' => [ @@ -448,6 +463,7 @@ Found 2 abandoned packages: ], 'reportedAt' => '2015-05-25 13:21:00', 'composerRepository' => 'https://packagist.org', + 'severity' => 'medium', ], ], 'vendor2/package1' => [ @@ -466,6 +482,7 @@ Found 2 abandoned packages: ], 'reportedAt' => '2022-05-25 13:21:00', 'composerRepository' => 'https://packagist.org', + 'severity' => 'medium', ], [ 'advisoryId' => 'ID6', @@ -482,6 +499,7 @@ Found 2 abandoned packages: ], 'reportedAt' => '2015-05-25 13:21:00', 'composerRepository' => 'https://packagist.org', + 'severity' => 'medium', ], ], 'vendory/packagey' => [ @@ -500,6 +518,7 @@ Found 2 abandoned packages: ], 'reportedAt' => '2015-05-25 13:21:00', 'composerRepository' => 'https://packagist.org', + 'severity' => 'medium', ], ], 'vendor3/package1' => [ @@ -518,6 +537,7 @@ Found 2 abandoned packages: ], 'reportedAt' => '2015-05-25 13:21:00', 'composerRepository' => 'https://packagist.org', + 'severity' => 'medium', ], ], ];