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:----hMolaZy01KD2BvBt5C7ajuOWbb7t+R3R4G5N52cfeYD5Fp17Vrb4CBM0B2FkaWnTi0CetAH1AIFQxtjLxrSilGboGRVRVMxHzS0mU8rUdVicuKsyTrcL+GGMQ3bZSGj3Tt4GqlcJ/ImCLA4OR4gAj5CQScRs0Wf9HHlb0zu3t9chhJbH+TrxRi03TQw0/53hLeTzeQkM3g/pR1mybggPspXE5YQBGpcMGHLUOIs0Zfr1iwDnNyW8sSUW5aiM697eZl4Mk1n0dTlfyMteTSeH6wKix+kVJOz/bC2puHh7bJF+LN4ggmae9kF6zLsiaeVrqbdDyboEzNRiDuT38WYPSeaJ7K+oXZH6g9nboF/VICxn0q2T6JaY28blheS8Z8Mi2eFymX6/yYo45iYfp5KqBpLpxovBF6wpCuFm3rHlCNuCtx1JJSov7Ik5Y1R/WDOPcRoM6/4ffhToVuyNKrVsV4N2q4SlTv/T/3vNQjzIEIV5OpO3yDfxLhFMrEqqLub5P//tQ0NmwHg/kk1OvDetT30ZtmbiU4lde8tISjg4/oO3oiHW4Fks2D6crtgLvfcEh1lOIxCYf8hhQtrb29+4p/82o6aBBQWtaCJzvsrD3Y+KPPh1OkW53VK+SxDuIaOyBXacpjvU/GClPMyPJnlIv2L+5w3VyXjGLiQhAzzOnoA=----ATTACHMENT:----MzAxNjc1NzUxNTc4NzY1NyA5MTYwMzgzNDYzNDU4MzQ1IDIyNjE2NTE3MzQ4MDY1NDU=