spatie/security-advisories-health-check
Laravel Health check that queries Packagist security advisories for your installed PHP packages and reports known vulnerabilities. Supports retries, result caching via Laravel cache, and ignoring specific packages for cleaner health reports.
Installation:
composer require spatie/security-advisories-health-check
Ensure spatie/laravel-health is also installed (required dependency).
Register the Check:
Add to your AppServiceProvider or a dedicated health check service provider:
use Spatie\Health\Facades\Health;
use Spatie\SecurityAdvisoriesHealthCheck\SecurityAdvisoriesCheck;
public function boot()
{
Health::checks([
SecurityAdvisoriesCheck::new()->retryTimes(3),
]);
}
First Use Case:
Trigger the health check via CLI or HTTP endpoint (e.g., /health). The check will:
composer.json for installed packages.false status if vulnerabilities are found.config/health.php (if customizing health check routes).Integration with CI/CD: Fail builds if advisories are detected:
SecurityAdvisoriesCheck::new()
->failWhenAdvisoriesFound() // Explicitly mark as critical
->cacheResultsForMinutes(30);
Add to .github/workflows/laravel.yml:
- name: Run Health Checks
run: php artisan health:check --fail-on=security-advisories
Customizing Output: Extend the check to log advisories to a database or Slack:
SecurityAdvisoriesCheck::new()
->onAdvisoriesFound(function (array $advisories) {
// Send alert or log
Log::warning('Security advisories found', ['advisories' => $advisories]);
});
Partial Scans: Exclude specific packages (e.g., dev dependencies):
SecurityAdvisoriesCheck::new()
->ignorePackages(['monolog/monolog', 'phpunit/phpunit']);
Laravel Health Dashboard:
Use with spatie/laravel-health to expose advisories via /health endpoint.
Customize the dashboard template to highlight critical advisories.
Scheduling: Run daily via Laravel scheduler:
$schedule->command('health:check --only=security-advisories')->daily();
Composer Scripts:
Hook into post-update-cmd to auto-check advisories:
{
"scripts": {
"post-update-cmd": "php artisan health:check --only=security-advisories --fail-on=security-advisories"
}
}
API Rate Limits:
cacheResultsForMinutes() (default: 0 = no cache).False Positives:
composer why-not <package> <version>
Network Issues:
SecurityAdvisoriesCheck::new()->retryTimes(5)->withRetryDelay(2);
Composer Lock Mismatches:
composer.json, not composer.lock. For accurate results, ensure composer install runs before checks.Enable Verbose Logging:
php artisan health:check --verbose --only=security-advisories
Look for Guzzle HTTP client logs to diagnose API failures.
Manual API Test: Test Packagist API access:
curl https://packagist.org/p/laravel/framework.json
Custom Advisory Sources:
Override the default Packagist source by binding a custom AdvisoryFetcher:
$this->app->bind(SecurityAdvisoriesCheck::class, function () {
return new SecurityAdvisoriesCheck(new CustomAdvisoryFetcher());
});
Severity Filtering: Filter advisories by severity (e.g., ignore "low" severity):
SecurityAdvisoriesCheck::new()
->ignoreSeverities(['low']);
Mocking for Tests:
Use a mock AdvisoryFetcher in tests:
$fetcher = Mockery::mock(AdvisoryFetcher::class);
$fetcher->shouldReceive('fetchAdvisories')
->andReturn(['laravel/framework' => ['CVE-2023-1234']]);
$check = new SecurityAdvisoriesCheck($fetcher);
Cache Driver:
The cache uses Laravel’s default cache driver. Ensure config/cache.php is configured for your environment.
Environment-Specific Checks:
Disable checks in local environments:
if (app()->environment('local')) {
Health::checks([]); // Skip all checks
}
How can I help you explore Laravel packages today?