> ## Content Index
> Fetch the complete content index at: https://securinglaravel.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Security Tip: Only Use env() Within Config Files
- URL: https://securinglaravel.com/security-tip-only-use-env-within-config-files/
- Published: 2024-05-05T15:00:00.000Z
- Updated: 2025-05-11T08:56:22.000Z
- Description: [Tip #79] It may be tempting to reach for env() outside your config files, but you may be introducing subtle bugs, or exposing your app to compromise...
- Author: Stephen Rees-Carter
- Tags: Security Tips, .env, Environment, Config

Laravel 11's new skeleton reduces the number of default config files down, and shifts more options directly into the `.env` file *(which* [*we've covered before*](https://securinglaravel.com/tag/env/)*)*. As a side effect of this, you might find yourself creating more config options within `.env`, or even just reaching for the values you've stored in `.env` more. 

If you do need to use the values within your `.env` file, **you need to ensure you only use the `env()` function within your `config/*.php` files!**

It may be tempting to use `env()` throughout your app *(I've seen it used a lot in Service classes!)*, and it will usually work fine during development, but the problem comes when your code hits production...

If your config is cached in production, i.e. by running the `php artisan config:cache` command, then your application will compile your config, including any variables from `.env` into a cache file, and only load that during requests. Any `env()` calls throughout the app will return `null`, because the variable doesn't exist.

This can break things entirely, introduce subtle bugs, or even expose your app to compromise... consider this code:

```php
if ($request->token === env('APP_API_TOKEN')) {
    // do sensitive stuff
}
```

If config is cached and the user passes an empty string, Laravel will convert it to `null`, which results in `null === null`, and the token is completely bypassed!

As was pointed out by *Martin Krisell* in the comments, this comparison should done using the `hash_equals()` method instead of the strict equals (`===`). Not only will `hash_equals()` [protect against timing attacks](https://securinglaravel.com/security-tip-compare-keys-with-hash%5Fequals/), but it also requires `string` inputs, making this harder to exploit.

---

***If you found this security tip useful,*** [***subscribe***](#/portal/signup) ***to get weekly*** [***Security Tips***](https://securinglaravel.com/tag/tips/) **straight to your inbox.* Upgrade to a* [*premium subscription*](#/portal/signup) *for exclusive monthly* [*In Depth articles*](https://securinglaravel.com/tag/in-depth/)*, or drop a coin in the* [*tip jar*](#/portal/support) *to show your support.*

*When was the last time you had a penetration test? Book a* [*Laravel Security Audit and Penetration Test*](https://stephenreescarter.net/laravel-security-audits-and-pentesting/?utm%5Fsource=securinglaravel.com)*, or a budget-friendly* [*Security Review*](https://stephenreescarter.net/laravel-security-reviews/?utm%5Fsource=securinglaravel.com)*!* 

*You can also connect with me on* [*Bluesky*](https://bsky.app/profile/valorin.bsky.social?ref=securinglaravel.com)*, or* [*other socials*](https://pinkary.com/@valorin?ref=securinglaravel.com)*, and check out* [*Practical Laravel Security*](https://practicallaravelsecurity.com/?utm%5Fsource=securinglaravel.com)*, my interactive course designed to boost your Laravel security skills.*