spatie/mixed-content-scanner-cli
CLI tool to detect mixed content on HTTPS sites. Crawls pages and reports HTML elements whose URLs use http:// (images, scripts, iframes, forms, etc.). Install via Composer globally and run: mixed-content-scanner scan .
Installation:
composer global require spatie/mixed-content-scanner-cli
Ensure $HOME/.composer/vendor/bin is in your PATH or use the full path to the binary.
First Scan:
mixed-content-scanner scan https://your-laravel-app.test
Replace with your Laravel app’s URL (e.g., local dev, staging, or production).
Key Flags:
--depth=N: Limit scan depth (default: 3).--ignore-urls: Exclude specific URLs (e.g., --ignore-urls="https://cdn.example.com").--output=json: Output results as JSON for programmatic use.Laravel Integration: Add a custom Artisan command (optional) to wrap the scanner:
php artisan make:command ScanMixedContent
Then extend it to call the scanner CLI tool.
CI/CD Integration:
phpunit.xml or GitHub Actions:
- name: Scan for mixed content
run: mixed-content-scanner scan https://your-app.test --output=json | jq -e '.mixedContent > 0' || exit 1
Local Development:
~/.bashrc or ~/.zshrc:
alias scan-mixed="mixed-content-scanner scan"
scan-mixed https://laravel-app.test --depth=2
Asset Pipeline Hooks:
deploy.php for Deployer):
run('mixed-content-scanner scan {{ release_url }} --ignore-urls="{{ asset_url }}"');
Programmatic Use:
$output = shell_exec('mixed-content-scanner scan https://example.com --output=json');
$data = json_decode($output, true);
if ($data['mixedContent'] > 0) {
Log::warning('Mixed content detected!', $data);
}
mix or Vite-manifest URLs in --ignore-urls to exclude self-hosted assets.local or staging environments (avoid production scans during business hours).local env to avoid repeated scans:
$cacheKey = 'mixed_content_scan_' . md5($url);
$result = Cache::remember($cacheKey, now()->addHour(), fn() => shell_exec(...));
False Positives:
https://cdn.example.com) may trigger warnings if the scanner misinterprets them as mixed.--ignore-urls for trusted CDNs or self-hosted assets:
--ignore-urls="https://cdn.example.com,http://localhost:3000"
Depth Limitations:
--depth=1) may miss nested mixed content (e.g., in iframes or dynamic loads).--depth=3 and adjust based on your app’s complexity.Dynamic Content:
Performance:
--depth=2 for critical paths.HTTPS Misconfigurations:
--insecure flag for local dev (not recommended for production):
mixed-content-scanner scan https://localhost --insecure
--verbose to debug scan paths:
mixed-content-scanner scan https://example.com --verbose
mixed-content-scanner scan https://example.com > scan.log
Connection refused: Ensure the URL is reachable (test with curl -v).SSL certificate problem: Update CA certificates or use --insecure (temporarily).Custom Rules:
src/Scanner.php to add custom URL validation logic (e.g., allow specific HTTP endpoints).Laravel Service Provider:
public function boot()
{
if (app()->environment('local')) {
$this->scanForMixedContent();
}
}
protected function scanForMixedContent()
{
$command = 'mixed-content-scanner scan '.config('app.url').' --ignore-urls="'.config('app.asset_url').'"';
$output = shell_exec($command);
// Handle output...
}
Database Logging:
mixed_content_scans table:
DB::table('mixed_content_scans')->insert([
'url' => $url,
'mixed_content_count' => $data['mixedContent'],
'scanned_at' => now(),
]);
Slack/Email Alerts:
if ($data['mixedContent'] > 0) {
Notification::route('mail', ['team@example.com'])
->notify(new MixedContentAlert($url, $data));
}
--timeout=30.mixed-content-scanner scan https://example.com --user-agent="Mozilla/5.0 (Laravel Scanner)"
robots.txt and avoid aggressive scanning of public sites.How can I help you explore Laravel packages today?