kev) { return self::EXPLOITED; } $severe = $finding->cvssScore !== null ? $finding->cvssScore >= self::LIKELY_SCORE : self::isSerious($finding); return $finding->epss !== null && $finding->epss >= self::LIKELY_EPSS && $severe ? self::LIKELY : null; } /** * Not ignored, not a CPE-only OS match, and an exploit signal, severity critical or high, or a counted medium. */ public static function isRelevant(Finding $finding, RelevanceRules $rules): bool { return ! self::isCpeOnlyOsMatch($finding) && (self::exploitSignal($finding) !== null || self::isSerious($finding) || self::isCountedMedium($finding, $rules->countMedium)) && $rules->ignores->matches($finding) === null; } /** * An OS package (apk, deb, rpm) that Grype matched only by CPE. */ public static function isCpeOnlyOsMatch(Finding $finding): bool { return str_starts_with(strtolower($finding->namespace), 'nvd:cpe') && in_array(strtolower($finding->type), self::OS_PACKAGE_TYPES, true); } /** * The IDs and aliases of the relevant findings, lowercase. * * @param list $findings * @return list */ public static function relevantIds(array $findings, RelevanceRules $rules): array { $ids = []; foreach ($findings as $finding) { if (self::isRelevant($finding, $rules)) { foreach ([$finding->id, ...$finding->aliases] as $id) { if ($id !== '') { $ids[] = mb_strtolower($id); } } } } return array_values(array_unique($ids)); } /** * A medium finding with EPSS 0.10 or more, or any medium finding when the rules count medium problems. Not an * exploit signal. */ private static function isCountedMedium(Finding $finding, bool $countMedium): bool { return strtolower($finding->severity) === 'medium' && ($countMedium || ($finding->epss !== null && $finding->epss >= self::LIKELY_EPSS)); } private static function isSerious(Finding $finding): bool { return in_array(strtolower($finding->severity), self::SERIOUS_SEVERITIES, true); } }