Laravel Debug Mode in Production: How to Disable APP_DEBUG and Stop Leaking Secrets

APP_DEBUG=true in production exposes stack traces, environment variables, and database credentials to anyone who triggers an error. Here is how to disable it safely and verify the fix.

Critical severity Application Security Updated 2026-03-01 Markdown

Laravel's debug mode was designed for the development workflow. When APP_DEBUG=true, the framework renders rich error pages through Ignition (or Whoops in older versions) that show stack traces, local variable values, environment variables, and even the full contents of your .env file. This makes debugging fast on a local machine — and catastrophically dangerous in production.

The mistake happens in several predictable ways: copying .env.example (which ships with APP_DEBUG=true) directly to production, enabling debug temporarily to troubleshoot an error and forgetting to disable it, or a deployment pipeline that doesn't enforce environment-specific configuration. Because Laravel caches configuration, a cached debug=true setting persists until config:clear is run, meaning the fix isn't immediate even after changing .env.

Ignition pages are indexed by search engines and actively targeted by attackers who search for app_debug=true and ignition in page sources. When Ignition's remote code execution vulnerability (CVE-2021-3129) was published, exploitation was widespread within 24 hours because so many Laravel apps had debug mode enabled in production. Even without RCE, the information disclosed — environment variables, file paths, database connection strings, installed package versions — gives an attacker everything needed to craft a targeted attack against your specific application.

The Problem

Having APP_DEBUG=true in production exposes detailed error pages that reveal your environment variables, database credentials, file paths, and full stack traces to anyone who triggers an error. This is the most common Laravel security misconfiguration and gives attackers a complete blueprint of your application internals. Laravel Ignition debug pages are regularly indexed by search engines.

How to Fix

  1. 1

    Set APP_DEBUG to false in your .env file

    Open your production .env file and change:

    APP_DEBUG=false
    APP_ENV=production
    Make sure there is no space around the equals sign and the value is exactly false (not "false" in quotes).
  2. 2

    Clear the configuration cache

    After changing the .env value, clear and rebuild the config cache:

    php artisan config:clear
    php artisan config:cache

    This ensures Laravel reads the updated value. Without clearing the cache, Laravel may continue using the cached debug=true setting.

  3. 3

    Configure proper error logging

    With debug mode off, you need proper error logging to catch issues. Configure your .env:

    LOG_CHANNEL=stack
    LOG_LEVEL=error

    For production monitoring, add an external service in config/logging.php:

    'channels' => [
        'stack' => [
            'driver' => 'stack',
            'channels' => ['daily', 'slack'],
        ],
        'slack' => [
            'driver' => 'slack',
            'url' => env('LOG_SLACK_WEBHOOK_URL'),
            'level' => 'error',
        ],
    ],
  4. 4

    Set up custom error pages

    Create user-friendly error pages so visitors see a professional page instead of a blank screen. Create these Blade files:

    resources/views/errors/404.blade.php resources/views/errors/500.blade.php resources/views/errors/503.blade.php

    Each should extend your app layout and show a helpful message without revealing technical details.

How to Verify

Visit a URL that does not exist on your site (e.g., yourdomain.com/this-page-does-not-exist). You should see a generic 404 page, not a Symfony or Ignition debug screen. Also verify with curl:

curl -s https://yourdomain.com/trigger-error | grep -i "whoops\|ignition\|debug\|stack trace"

This command should return nothing.

Prevention

Never set APP_DEBUG in your production deployment pipeline. Use environment-specific .env files and add APP_DEBUG=true to your .env.example with a comment warning against using it in production. Monitor with StackShield to catch accidental debug mode activation after deployments.

Frequently Asked Questions

What information does debug mode expose?

Debug mode exposes your full .env contents (database credentials, API keys, APP_KEY), complete stack traces with file paths, server PHP version, installed package versions, SQL queries, and request data. This is enough for an attacker to fully compromise your application.

Can I have debug mode on for specific IPs only?

Laravel does not support IP-based debug mode natively. Instead, use Laravel Telescope for debugging in production with authentication. Install it with composer require laravel/telescope, then restrict access in TelescopeServiceProvider using the gate() method to allow only admin users.

How do developers accidentally enable debug mode in production?

The most common causes are: copying .env.example (which has APP_DEBUG=true) to .env on the server, enabling debug temporarily to troubleshoot and forgetting to disable it, and deployment scripts that do not set environment-specific values. A cached config with debug=true persists even after changing .env until you run config:clear.

How do I verify debug mode is off without triggering an actual error?

Run php artisan config:show app | grep debug in your terminal to see the current runtime value. Alternatively, run php artisan tinker and enter config("app.debug") — it should return false. Do not rely on checking the .env file alone if config caching is active, since the cache may not reflect recent changes.

Should staging and production have separate .env files?

Yes, always. Staging should have APP_DEBUG=false and APP_ENV=staging with its own separate database and API credentials. Sharing .env files between environments risks production credentials being used in staging (where access controls are typically looser) and also prevents staging from accurately reflecting what production will behave like.

Related Security Terms

Free security check

Is your Laravel app exposed right now?

34% of Laravel apps we scan have at least one critical issue. Most teams don't find out until something breaks. Our free scan checks your live application in under 60 seconds.

18% have debug mode on
72% missing security headers
12% have exposed .env
Scan My App Free No signup required. Results in 60 seconds.