laramint/laravel-security-scanner
Installation
composer require --dev laramint/laravel-security-scanner
The package auto-discovers via composer/installed.json. For manual invocation:
vendor/bin/php-security-scanner --extension=LaraMint\LaravelSecurityScanner\LaravelExtension
First Scan Run the scanner on your Laravel project root:
vendor/bin/php-security-scanner .
Focus on critical/high severity issues first (e.g., SQL injection, auth bypass).
Key Flags
laravel.sql-injection, laravel.unsafe-auth, laravel.artisan-calllaravel.mass-assignment, laravel.unsafe-validator, laravel.file-upload-validationPre-Commit Hook Integrate with Git hooks to scan before commits:
echo 'vendor/bin/php-security-scanner .' >> .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
Tip: Use --severity=high,critical to avoid noise.
CI/CD Pipeline Add to Laravel CI (e.g., GitHub Actions):
- name: Security Scan
run: vendor/bin/php-security-scanner --severity=high,critical --extension=LaraMint\LaravelSecurityScanner\LaravelExtension .
Fail the build on critical issues.
Targeted Scans
routes/ for redirect()->to($tainted) or View::make($tainted).update(), store(), and Auth::loginUsingId().Artisan::call($tainted) or Process::run($tainted).False Positive Handling
Suppress known-safe patterns via .php-security-scanner.json:
{
"rules": {
"laravel.sql-injection": {
"paths": ["app/Helpers/SqlBuilder.php"]
}
}
}
phpstan or psalm alongside the scanner for static analysis.AbstractRule for project-specific checks (e.g., internal API endpoints).request() methods (e.g., $request->input('user_id')) as taint sources in custom rules.Overly Broad Exceptions
laravel.sql-injection for entire files unless 100% sure of safety (e.g., ORM-generated raw queries).whereRaw("CAST($value AS INT)") may still be unsafe if $value is tainted.Blade False Positives
{!! $safeVar !!} triggers laravel.blade-raw-echo, but may be intentional (e.g., trusted HTML from a CMS).{{ $var }} or explicitly mark as safe in custom rules.Environment Leaks
env('APP_KEY') in Blade/views triggers laravel.env-leak even if cached.Taint Propagation
request()->input() is tainted, but intermediate processing (e.g., strtolower()) may not clear taint.LaravelExtension::clearTaint() in custom rules for sanitized data.Artisan/Process Commands
Artisan::call('migrate:fresh') is safe, but Artisan::call($userInput) is critical.Process facade (v10+) also triggers laravel.process-shell.--verbose to see taint flow:
vendor/bin/php-security-scanner --verbose .
vendor/bin/php-security-scanner --rule=laravel.sql-injection .
// @phpstan-ignore-next-line temporarily to trace taint sources.Custom Taint Sources
Override LaravelExtension::register() to add project-specific sources:
$extension->addTaintSource('app()->make(\App\Services\UntrustedService::class)');
Severity Tuning
Adjust default severities in config/php-security-scanner.php:
'rules' => [
'laravel.debug-code' => 'low', // Downgrade debug leaks
],
Dynamic Analysis
Combine with phpstan for deeper static analysis:
vendor/bin/phpstan analyse --level=max --generate-report=html
Performance
Exclude vendor/ and node_modules/ from scans:
vendor/bin/php-security-scanner --exclude=vendor,node_modules .
How can I help you explore Laravel packages today?