function Auditor::audit
Parameters
PackageInterface[] $packages:
self::FORMAT_* $format The format that will be used to output audit results.:
bool $warningOnly If true, outputs a warning. If false, outputs an error.:
string[] $ignoreList List of advisory IDs, remote IDs or CVE IDs that reported but not listed as vulnerabilities.:
self::ABANDONED_* $abandoned:
array<string> $ignoredSeverities List of ignored severity levels:
Return value
int Amount of packages with vulnerabilities found
Throws
InvalidArgumentException If no packages are passed in
File
-
vendor/
composer/ composer/ src/ Composer/ Advisory/ Auditor.php, line 67
Class
- Auditor
- @internal
Namespace
Composer\AdvisoryCode
public function audit(IOInterface $io, RepositorySet $repoSet, array $packages, string $format, bool $warningOnly = true, array $ignoreList = [], string $abandoned = self::ABANDONED_FAIL, array $ignoredSeverities = []) : int {
$allAdvisories = $repoSet->getMatchingSecurityAdvisories($packages, $format === self::FORMAT_SUMMARY);
// we need the CVE & remote IDs set to filter ignores correctly so if we have any matches using the optimized codepath above
// and ignores are set then we need to query again the full data to make sure it can be filtered
if (count($allAdvisories) > 0 && $ignoreList !== [] && $format === self::FORMAT_SUMMARY) {
$allAdvisories = $repoSet->getMatchingSecurityAdvisories($packages, false);
}
[
'advisories' => $advisories,
'ignoredAdvisories' => $ignoredAdvisories,
] = $this->processAdvisories($allAdvisories, $ignoreList, $ignoredSeverities);
$abandonedCount = 0;
$affectedPackagesCount = 0;
if ($abandoned === self::ABANDONED_IGNORE) {
$abandonedPackages = [];
}
else {
$abandonedPackages = $this->filterAbandonedPackages($packages);
if ($abandoned === self::ABANDONED_FAIL) {
$abandonedCount = count($abandonedPackages);
}
}
if (self::FORMAT_JSON === $format) {
$json = [
'advisories' => $advisories,
];
if ($ignoredAdvisories !== []) {
$json['ignored-advisories'] = $ignoredAdvisories;
}
$json['abandoned'] = array_reduce($abandonedPackages, static function (array $carry, CompletePackageInterface $package) : array {
$carry[$package->getPrettyName()] = $package->getReplacementPackage();
return $carry;
}, []);
$io->write(JsonFile::encode($json));
return count($advisories) + $abandonedCount;
}
$errorOrWarn = $warningOnly ? 'warning' : 'error';
if (count($advisories) > 0 || count($ignoredAdvisories) > 0) {
$passes = [
[
$ignoredAdvisories,
"<info>Found %d ignored security vulnerability advisor%s affecting %d package%s%s</info>",
],
// this has to run last to allow $affectedPackagesCount in the return statement to be correct
[
$advisories,
"<{$errorOrWarn}>Found %d security vulnerability advisor%s affecting %d package%s%s</{$errorOrWarn}>",
],
];
foreach ($passes as [
$advisoriesToOutput,
$message,
]) {
[
$affectedPackagesCount,
$totalAdvisoryCount,
] = $this->countAdvisories($advisoriesToOutput);
if ($affectedPackagesCount > 0) {
$plurality = $totalAdvisoryCount === 1 ? 'y' : 'ies';
$pkgPlurality = $affectedPackagesCount === 1 ? '' : 's';
$punctuation = $format === 'summary' ? '.' : ':';
$io->writeError(sprintf($message, $totalAdvisoryCount, $plurality, $affectedPackagesCount, $pkgPlurality, $punctuation));
$this->outputAdvisories($io, $advisoriesToOutput, $format);
}
}
if ($format === self::FORMAT_SUMMARY) {
$io->writeError('Run "composer audit" for a full list of advisories.');
}
}
else {
$io->writeError('<info>No security vulnerability advisories found.</info>');
}
if (count($abandonedPackages) > 0 && $format !== self::FORMAT_SUMMARY) {
$this->outputAbandonedPackages($io, $abandonedPackages, $format);
}
return $affectedPackagesCount + $abandonedCount;
}