Custom Error Pages Analyzer
| Analyzer ID | Category | Severity | Time To Fix |
|---|---|---|---|
custom-error-pages | ✅ Reliability | Low | 30 minutes |
What This Checks
This analyzer validates the conventional Laravel approach of creating individual error template files in resources/views/errors/:
401.blade.php- Unauthorized (authentication required)403.blade.php- Forbidden (authorization failed)404.blade.php- Not Found419.blade.php- Page Expired (CSRF token mismatch)429.blade.php- Too Many Requests (rate limiting)500.blade.php- Internal Server Error503.blade.php- Service Unavailable (maintenance mode)
What this analyzer checks:
- Existence of conventional error template files on the filesystem
- All configured view paths and custom error view namespaces
- Skips stateless/API-only apps (no session middleware)
What this analyzer does NOT check:
- Custom exception handlers in
app/Exceptions/Handler.php - Dynamic error views (single template handling multiple HTTP codes)
- Middleware-level error response overrides
- Custom render methods on exception classes
- Error responses returned from controllers
Important
Applications can implement custom error handling through various approaches. If you use custom exception handlers or other non-conventional methods, you can safely ignore this warning.
Why It Matters
- Framework fingerprinting: Default error pages advertise "Laravel", helping attackers tailor exploits
- Security exposure: CSRF errors (419) and authorization failures (401, 403) revealing framework details can guide attacks
- User experience: Users prefer branded error pages with recovery instructions (contact support, try again)
- Rate limiting clarity: Custom 429 pages can explain retry timing and help prevent support tickets
- Consistency: Custom error pages maintain brand experience even during failures or maintenance
How to Fix
Custom error handling can be implemented in several ways. Choose the approach that best fits your architecture:
Approach 1: Conventional File-Based (Checked by This Analyzer)
Quick Fix (15 minutes):
- Publish the default error views:
php artisan vendor:publish --tag=laravel-errors- Customize all error templates in
resources/views/errors/:401.blade.php- Unauthorized403.blade.php- Forbidden404.blade.php- Not Found419.blade.php- Page Expired (CSRF)429.blade.php- Too Many Requests500.blade.php- Internal Server Error503.blade.php- Service Unavailable
Best Practices:
- Add helpful CTAs (support links, status pages, recovery instructions)
- Display correlation/request IDs for debugging
- Localize error messages for multilingual apps
- Write feature tests to verify templates render correctly
Approach 2: Custom Exception Handler
Override the render() method in app/Exceptions/Handler.php:
public function render($request, Throwable $e)
{
if ($e instanceof NotFoundHttpException) {
return response()->view('errors.custom-404', [], 404);
}
if ($e instanceof AuthorizationException) {
return response()->view('errors.custom-403', [], 403);
}
return parent::render($request, $e);
}Approach 3: Dynamic Error View
Create a single template that handles all error codes:
{{-- resources/views/errors/error.blade.php --}}
@switch($exception->getStatusCode())
@case(404)
<h1>Page Not Found</h1>
@case(500)
<h1>Server Error</h1>
@default
<h1>An Error Occurred</h1>
@endswitchApproach 4: Middleware-Based
Transform error responses in middleware:
public function handle($request, Closure $next)
{
$response = $next($request);
if ($response->status() >= 400) {
return response()->view('errors.handler', [
'code' => $response->status()
], $response->status());
}
return $response;
}Skipping This Analyzer
If you use approaches 2-4, add to config/shieldci.php:
'dont_report' => [
'custom-error-pages',
],ShieldCI Configuration
This analyzer is automatically skipped for stateless/API-only applications.
Why skip for stateless/API-only apps?
- API-only applications return JSON error responses, not HTML pages
- Stateless apps (no session middleware) don't serve traditional web pages
- Custom HTML error pages aren't relevant for pure API applications
When to run this analyzer:
- ✅ Web applications with sessions: Full-stack Laravel apps serving HTML
- ✅ Hybrid apps: Applications with both web and API routes
- ✅ Local development: Ensures error pages are configured before deployment
- ✅ Staging/Production servers: Validates custom error pages are in place
- ❌ API-only applications: Skipped automatically (no session middleware detected)
References
Related Analyzers
- Cache Status Analyzer - Validates cache connectivity and functionality
- Cache Prefix Configuration Analyzer - Ensures cache prefix is set to avoid collisions
- Maintenance Mode Status Analyzer - Checks if the application is in maintenance mode