12 Laravel security best practices for 2023

https://res.cloudinary.com/benjamin-crozat/image/upload/dpr_auto,f_auto,q_auto,w_auto/v1690645860/dhjbi100_uiarfm.png

Don’t track your .env file

Your .env file contains sensitive information.

Please, don’t track it!

Make sure it’s included in your .gitignore.

Most of the time, data leaks are inside jobs.

A password manager is a better solution for sharing credentials.

If you want your team members to have access to a curated set of sensitive information, use a password manager with a proven track record of rock-solid security.

Keep Laravel up to date

Keeping Laravel up to date allows you to stay in touch with the latest security updates.

Make sure you are running a version of Laravel that is still being patched, and you should be OK.

If you never upgraded a Laravel project, I wrote a guide that will teach you how to do it.

Keep your first and third-party packages up to date

Access to dozens of packages from the official Laravel ecosystem and thousands of community packages is what makes our job easier.

But the more packages you use, the more points of failure you can be subject to.

Regularly running composer update goes a long way toward a more secure codebase.

composer update in action.

Disable debug messages in production

Make sure these two environment variables are correctly set in production.

APP_ENV=production

APP_DEBUG=false

You don’t want to leak information about your app’s architecture or configuration. Usually, debug messages contain a lot of this kind of details.

Don’t send sensitive information to error monitoring tools

Talking about sensitive information in debug messages, we haven’t eradicated them yet.

If you are using an error monitoring tool, you have to them there as well.

PHP 8.2 introduced a new attribute, \SensitiveParameter, that can hide anything from the stack trace (which is sent to error monitoring tools).

function something(

#[\SensitiveParameter]

$top_secret_parameter,

$who_cares_parameter,

) {

throw new \Exception('Whoops, something bad happended!');

}

Restrict parts of your app with policies

Policies in Laravel are like nightclub bouncers preventing people from accessing restricted areas.

Let’s look at a real-world example of using a Policy:

// app/Policies/PostPolicy.php

public function update(User $user, Post $post)

{

return $user->id === $post->user_id;

}

 

// app/Http/Controllers/PostController.php

public function update(Request $request, Post $post)

{

$this->authorize('update', $post);

 

// ...

}

As you can see, they make it really easy to check for permission before allowing a user to do anything.

Make sure to check the documentation, because there’s a lot to learn about Policies.

Protect your forms from cross-site request forgery (CSRF)

You might want to use the @csrf Blade directive in your forms.

<form method="POST" action="">

@csrf

 

<p>

<label for="name">First Name</label>

<input type="text" id="name" name="name" value="" required />

</p>

 

</form>

This directive generates a hidden input field containing a CSRF token automatically included when submitting the form.

This token confirms that the form is being submitted from your application and not by a third party.

The verification is handled by the VerifyCsrfToken middleware that Laravel uses by default for all your web routes.

Learn more about CSRF protection in Laravel’s documentation.

Validate the user’s input

Validation in Laravel is crucial in ensuring your application’s security.

Validation rules are numerous and will help you sanitize the data your users send with ease. Because you know the drill, right? Never trust your users’ input.

use Illuminate\Http\Request;

 

class PostController extends Controller

{

function store(Request $request)

{

$validated = $request->validate([

'user_id' => 'required|exists:users,id',

'title' => 'required|string|min:3|max:255',

'content' => 'required|string|min:3',

'published' => 'sometimes|boolean'

]);

 

Post::create($validated);

 

//

}

}

Learn more about validation in Laravel on the official documentation.

Be careful with uploaded files

As we saw, the user’s input must never be trusted. That also goes for the files they upload. Here are a few recommendations:

  1. Check the file’s MIME type (Laravel has the right validation rules for that).

$request->validate([

'file' => 'required|mimes:gif,jpeg,png,webp',

]);

  1. When possible, don’t make uploaded files publicly accessible (using the local file driver, for instance).

  2. Upload files on another server. If a hacker bypasses your securities, they won’t be able to run unauthorized code and access sensitive information.

  3. Delegate file uploads to a third-party service reputed for its security (meaning they never leaked data).

Encrypt the payload of your jobs

Whenever you dispatch a job, its payload is saved into the database, Redis or whatever else you told Laravel to use using the QUEUE_DRIVER environment variable.

The payload may contain sensitive information that any of your employee may look at and potentially misuse. As I said in the beginning of this article, leaks are often initiated by employees.

Fortunately, Laravel provides a the Illuminate\Contracts\Queue\ShouldBeEncrypted Contract, which will automatically encrypt the payloads. To make sure nobody can unencrypt them, make sure the Laravel’s APP_KEY defined in your .env is unaccessible to anyone besides a few trusted people.

use Illuminate\Contracts\Queue\ShouldQueue;

use Illuminate\Contracts\Queue\ShouldBeEncrypted;

 

class SomeJob implements ShouldQueue, ShouldBeEncrypted

{

//

}

Write tests for security risks

Testing is unfortunately a vast and lesser-known topic among developers.

Automatically testing multiple scenarii for potential security breaches is a great way to make sure they stay closed.

Laracasts provides free testing courses to help you get started. One with PHPUnit, the industry standard, and one with Pest, the best testing framework on this planet that modernizes and simplifies testing in PHP.

Keep your project tested

Do regular security audits

This practice is one of the most efficient and should be mandatory for anyone that is really serious about security. External feedback can be eyes opening.

As you can imagine, doing security audits isn’t free. It might only be worth it for enterprise since it would cost even more to pay for the potential fines! You cannot put a price on maintaining a good reputation and the trust of your users.

Laravel News Links