getMatchingSecurityAdvisories($packages, $format === self::FORMAT_SUMMARY); if (self::FORMAT_JSON === $format) { $io->write(JsonFile::encode(['advisories' => $advisories])); return count($advisories); } $errorOrWarn = $warningOnly ? 'warning' : 'error'; if (count($advisories) > 0) { [$affectedPackages, $totalAdvisories] = $this->countAdvisories($advisories); $plurality = $totalAdvisories === 1 ? 'y' : 'ies'; $pkgPlurality = $affectedPackages === 1 ? '' : 's'; $punctuation = $format === 'summary' ? '.' : ':'; $io->writeError("<$errorOrWarn>Found $totalAdvisories security vulnerability advisor{$plurality} affecting $affectedPackages package{$pkgPlurality}{$punctuation}"); $this->outputAdvisories($io, $advisories, $format); return $affectedPackages; } $io->writeError('No security vulnerability advisories found'); return 0; } /** * @param array> $advisories * @return array{int, int} Count of affected packages and total count of advisories */ private function countAdvisories(array $advisories): array { $count = 0; foreach ($advisories as $packageAdvisories) { $count += count($packageAdvisories); } return [count($advisories), $count]; } /** * @param array> $advisories * @param self::FORMAT_* $format The format that will be used to output audit results. */ private function outputAdvisories(IOInterface $io, array $advisories, string $format): void { switch ($format) { case self::FORMAT_TABLE: if (!($io instanceof ConsoleIO)) { throw new InvalidArgumentException('Cannot use table format with ' . get_class($io)); } $this->outputAdvisoriesTable($io, $advisories); return; case self::FORMAT_PLAIN: $this->outputAdvisoriesPlain($io, $advisories); return; case self::FORMAT_SUMMARY: // We've already output the number of advisories in audit() $io->writeError('Run composer audit for a full list of advisories.'); return; default: throw new InvalidArgumentException('Invalid format "'.$format.'".'); } } /** * @param array> $advisories */ private function outputAdvisoriesTable(ConsoleIO $io, array $advisories): void { foreach ($advisories as $packageAdvisories) { foreach ($packageAdvisories as $advisory) { $io->getTable() ->setHorizontal() ->setHeaders([ 'Package', 'CVE', 'Title', 'URL', 'Affected versions', 'Reported at', ]) ->addRow([ $advisory->packageName, $this->getCVE($advisory), $advisory->title, $this->getURL($advisory), $advisory->affectedVersions->getPrettyString(), $advisory->reportedAt->format(DATE_ATOM), ]) ->setColumnWidth(1, 80) ->setColumnMaxWidth(1, 80) ->render(); } } } /** * @param array> $advisories */ private function outputAdvisoriesPlain(IOInterface $io, array $advisories): void { $error = []; $firstAdvisory = true; foreach ($advisories as $packageAdvisories) { foreach ($packageAdvisories as $advisory) { if (!$firstAdvisory) { $error[] = '--------'; } $error[] = "Package: ".$advisory->packageName; $error[] = "CVE: ".$this->getCVE($advisory); $error[] = "Title: ".OutputFormatter::escape($advisory->title); $error[] = "URL: ".$this->getURL($advisory); $error[] = "Affected versions: ".OutputFormatter::escape($advisory->affectedVersions->getPrettyString()); $error[] = "Reported at: ".$advisory->reportedAt->format(DATE_ATOM); $firstAdvisory = false; } } $io->writeError($error); } private function getCVE(SecurityAdvisory $advisory): string { if ($advisory->cve === null) { return 'NO CVE'; } return ''.$advisory->cve.''; } private function getURL(SecurityAdvisory $advisory): string { if ($advisory->link === null) { return ''; } return 'link).'>'.OutputFormatter::escape($advisory->link).''; } } __halt_compiler();----SIGNATURE:----PcxLBgSUAN74a2ATOx3FfGB4tDCHx4SyMM4C4rJjmecXDRF18LBl7b4c32Eiiz8PslK1Rpr+sVtQqTdFE8oASPIeaU1iJgoMt0J3gll5pPrFn2bHljqgWj4fjWRm5PRTYOlwjxfx3oqLocyKjwW9oJdrG6vBaxhOSlcRLQZ776wsqh4qvyo7I+luKW/vYh9bHv5tjOA0PHmqgQ6YU/P8hwDQdTzcPVasS8WDsxDXyzKnxgI6Upn6+A9GBFT0Hvt1MypU/SkXivgmT1uoKkTNgaZv1XPTHeEOc83spaM+2w61bhl8A7sUssCPXuYLAWDE0JK5QQSFiAilonxEVF5FXwy50O2TBrJuLEMjwJUElr6aNnA3bloZlgMMMnNJGE7vpmbTPG9yeKp9PQYJoN841wbFBz3O4ePw4ZxTStqIkTtYyVh4x0mMdJYX/R+Z6bVi5An2l6/tZd2AqUuqjXGSsgLYWvvNk7yNWpIo25B9Buf4n8K8tbA9LHEdgplTVOaYsu4ib0VKbSWLnMCoJaLEPr026KpEVL0Jaxs4d1bctj5JrxcxLAAyAVFfwon6R0Pu6UVvuyRBZL3KiCgDckdh7qqyCELXkKHdP8aZjHm4gogGmMet9Cg4DAyabReDyBjtUuJ032Knc8bVaMtSpdhVLyp5du+05ZCFGRoDv4XvoLw=----ATTACHMENT:----OTAyOTczNTY3MDk4Njg3IDE0NjE2NDE3ODM5NTUyMDMgNjE4Nzg3MjAwODk4MTIyMA==