

Discover more from Securing Laravel
Security Tip: Disable Debug Mode on World-accessible Apps
[Tip#59] It may seem obvious, you'd be surprised just how often I come across websites where debug mode is enabled!
đ”ïž There is one slot left in December for a Laravel Security Audit and Penetration Test, get in quick for an audit before the end of the year! âš
One of the first (and most important!) things you should do when deploying code into a world-accessible location is to disable debug mode. Itâs something I discover all the time on random websites, and Iâve often heard arguments that itâs useful for debugging, but none of that outweighs the massive security risk of having debug mode enabled. So make it the first thing you do when deploying your code!
In Laravel, this is as simple as setting the `APP_DEBUG`
environment variable to `false`
within your `.env`
file:
APP_DEBUG=false
Setting `APP_DEBUG`
to `false`
disables the fancy error page that displays a significant amount of sensitive information about your app. This error page, and the information it contains, can leak all sorts of information, and is a gold mine for anyone trying to hack into your app or steal your userâs data.
Error messages themselves can also leak information - such as the full SQL query, or file paths, both of which are incredibly useful when trying to exploit a vulnerability, such as SQL Injection (SQLi), or Local File Inclusion (LFI).
While youâre at it, donât forget to update `APP_ENV`
to `production`
, to instruct the app that itâs world-accessible and disable any other debugging features1.
APP_ENV=production
My Recommendation
I recommend you update your `.env.example`
to have `APP_DEBUG=false`
and `APP_ENV=production`
set by default. This does mean you need to modify it any time youâre setting up a local dev, but it prevents you from deploying your code online, copying `.env.example â .env`
, and forgetting to disable debug mode.
Trust me, a little pain in local dev is worth it to prevent a breach in production!
As an example, hereâs the top of my `.env.example`
for my Practical Laravel Security course:
APP_NAME="Practical Laravel Security"
APP_ENV=production
APP_KEY=
APP_DEBUG=false
APP_URL=https://practicallaravelsecurity.app
What do I mean by âworld-accessibleâ?
If the app can be accessed by anyone on the internet, then itâs world-accessible.
This doesnât just mean production, but also staging, testing, and QA sites too. If a random person can discover the URL somehow and visit it, then itâs world-accessible.
If someone can break into your staging site - which is likely to be buggy and may have security vulnerabilities due to active development - they can then use this to pivot into your production site2, or directly attack your developers. Having debug mode on these sites makes it even easier to compromise them, and in turn, makes it easier to attack production too.
As a side note, I recommend keeping staging, testing, QA, etc, sites on separate root domains and locked behind firewalls or Basic Auth. This makes them harder to find, less exploitable3, and if auth is required before any code is touched, any weaknesses in dev code canât be easily exploited.
Looking to learn more?
â© Security Tip #40: Retrieving Request Values
â¶ïž In Depth #13: Stealing Password Tokens with Forwarded Host Poisoning
Do I need to write a dedicated article about this too?
Through things like shared credentials, bypassing same-site productions if the sites share the same root domain, etc. Or maybe you have prod data on staging? There are a lot of optionsâŠ
As being on the same-site as production is no longer a concern.
Security Tip: Disable Debug Mode on World-accessible Apps
There is a more comprehensive way that we prefer to use, which is to check in the middleware, and then check for that middleware variable in the blade. That lets people test in âproductionâ (which may be behind internal firewalls so reasonably safe) but also lets us expose the âyouâve got debug turned on in prod!!!â message in the default layout blade in a way that canât be missed. https://github.com/snipe/snipe-it/blob/master/app/Http/Middleware/CheckForDebug.php