Laravel Debug Mode

Easy

Checks if Laravel debug mode is enabled in production.

Estimated fix time: 5 minutes

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

  1. Set APP_DEBUG=false in .env
  2. Clear config cache: php artisan config:cache
  3. Trigger an error (visit non-existent route)
  4. Verify you see a generic error page, NOT a stack trace
  5. 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:

  1. Immediately disable:

    # SSH to server
    vim .env
    # Set APP_DEBUG=false
    php artisan config:cache
    
  2. Rotate all secrets:

    php artisan key:generate
    # Update database passwords
    # Rotate API keys
    
  3. Check logs for unauthorized access:

    grep "error" storage/logs/laravel.log
    
  4. Assess exposure:

    • What errors were shown?
    • What credentials were visible?
    • Review web server access logs
  • 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
Was this guide helpful?