Laravel Debug Mode
EasyChecks if Laravel debug mode is enabled in production.
What is Debug Mode?
Laravel's debug mode displays detailed error pages with stack traces, configuration details, and environment information. This is invaluable during development but exposes critical security information in production.
Security Impact
Severity: Critical
- Exposed application paths and structure
- Database credentials visible
- API keys and secrets revealed
- Stack traces showing code logic
- Dependency versions exposed
- Enables vulnerability reconnaissance
How to Fix
1. Update .env File
# .env
APP_ENV=production
APP_DEBUG=false
2. Clear Configuration Cache
# Clear cached config
php artisan config:clear
# Cache new configuration
php artisan config:cache
# Clear all caches
php artisan cache:clear
php artisan view:clear
php artisan route:clear
3. Verify Environment Detection
// config/app.php
'debug' => (bool) env('APP_DEBUG', false),
// Ensure this evaluates to false in production
4. Configure Custom Error Pages
Create custom error views:
# Create error views
php artisan vendor:publish --tag=laravel-errors
{{-- resources/views/errors/500.blade.php --}}
<!DOCTYPE html>
<html>
<head>
<title>Server Error</title>
</head>
<body>
<h1>Something went wrong</h1>
<p>We're working on fixing the issue. Please try again later.</p>
</body>
</html>
5. Implement Proper Error Logging
// config/logging.php
'channels' => [
'production' => [
'driver' => 'stack',
'channels' => ['daily', 'slack'],
'ignore_exceptions' => false,
],
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/laravel.log'),
'level' => 'error',
'days' => 14,
],
],
LOG_CHANNEL=production
LOG_LEVEL=error
6. Configure Error Reporting
// app/Exceptions/Handler.php
public function register()
{
$this->reportable(function (Throwable $e) {
// Log to monitoring service
if (app()->environment('production')) {
// Send to error tracking service (Sentry, Bugsnag, etc.)
}
});
}
public function render($request, Throwable $e)
{
if (app()->environment('production')) {
if ($e instanceof \Symfony\Component\HttpKernel\Exception\NotFoundHttpException) {
return response()->view('errors.404', [], 404);
}
return response()->view('errors.500', [], 500);
}
return parent::render($request, $e);
}
Verification Steps
- Set
APP_DEBUG=falsein.env - Clear config cache:
php artisan config:cache - Trigger an error (visit non-existent route)
- Verify you see a generic error page, NOT a stack trace
- Check error logs to ensure logging still works
Production Environment Best Practices
1. Environment-Specific Configuration
// config/app.php
'debug' => env('APP_DEBUG', false),
'debug_blacklist' => [
'_ENV' => [
'APP_KEY',
'DB_PASSWORD',
'REDIS_PASSWORD',
'MAIL_PASSWORD',
'AWS_SECRET_ACCESS_KEY',
],
'_SERVER' => [
'APP_KEY',
'DB_PASSWORD',
],
],
2. Use Error Tracking Services
Sentry Integration:
composer require sentry/sentry-laravel
php artisan vendor:publish --provider="Sentry\Laravel\ServiceProvider"
SENTRY_LARAVEL_DSN=your-dsn-here
SENTRY_TRACES_SAMPLE_RATE=0.1
Bugsnag Integration:
composer require bugsnag/bugsnag-laravel
// config/bugsnag.php
'api_key' => env('BUGSNAG_API_KEY'),
'release_stage' => env('APP_ENV', 'production'),
3. Secure Error Logging
// Don't log sensitive data
public function report()
{
if ($this->exception instanceof CustomException) {
$this->exception->message = 'Sanitized error message';
}
}
4. Health Check Endpoint
// routes/api.php
Route::get('/health', function () {
return response()->json([
'status' => 'ok',
'timestamp' => now()->toIso8601String(),
]);
});
Deployment Checklist
Before deploying to production:
-
APP_ENV=production -
APP_DEBUG=false - Config cached:
php artisan config:cache - Routes cached:
php artisan route:cache - Views cached:
php artisan view:cache - Custom error pages created
- Error tracking service configured
- Log monitoring set up
- Verified debug mode is disabled
Automated Testing
// tests/Feature/DebugModeTest.php
public function test_debug_mode_is_disabled_in_production()
{
config(['app.env' => 'production']);
$this->assertFalse(config('app.debug'));
}
public function test_error_pages_dont_expose_details()
{
config(['app.env' => 'production', 'app.debug' => false]);
$response = $this->get('/non-existent-route');
$response->assertStatus(404);
$response->assertDontSee('stack trace');
$response->assertDontSee('APP_KEY');
$response->assertDontSee('DB_PASSWORD');
}
Emergency Response
If debug mode was enabled in production:
-
Immediately disable:
# SSH to server vim .env # Set APP_DEBUG=false php artisan config:cache -
Rotate all secrets:
php artisan key:generate # Update database passwords # Rotate API keys -
Check logs for unauthorized access:
grep "error" storage/logs/laravel.log -
Assess exposure:
- What errors were shown?
- What credentials were visible?
- Review web server access logs
Related Issues
- Ignition Exposure
- Telescope Exposure
- Exposed .env Files
- Sensitive Files
Automatically detect this issue
StackShield can automatically scan your Laravel application for this security issue and alert you when it's detected.
Start Free Trial