8 Security Best Practices in Laravel

Danushaka Dissanayaka
7 min readJul 16, 2024

--

Many new developers question whether Laravel is secure or not. Laravel offers various security features, but the framework itself is neither inherently secure nor insecure. It is as secure as the measures implemented by the developers. Lets discuss some security practices to focus on while developing a Laravel application.

Don’t Use $request->all()

Using $request->all() in your store or update methods can introduce security vulnerabilities by not filtering input from the frontend or API. For example if your database has a field like is_admin and it is fillable in the Eloquent model someone could guess this field name and add it to the form data by modifying the HTML.

Instead of using $request->all() use form request classes for validation, and then use $request->validated(). Specify the exact fields you expect from the form using $request->only() or $request->except() to protect your database from malicious input.

File Upload with Client Data

File uploads can also pose security risks. Using methods like $file->getClientOriginalName() or $file->getClientOriginalExtension() can be unsafe becuse file name and extension can be intentionally modify by a malicious user inorder to bypass your application security

Laravel’s documentation states about this methods

“Keep in mind that the getClientOriginalName and getClientOriginalExtension methods are considered unsafe, as the file name and extension may be tampered with by a malicious user. For this reason, you should typically prefer the hashName and extension methods to get a name and an extension for the given file upload.”

Instead of using these unsafe methods, use hashName() and extension() to get a secure name and extension for the uploaded file.

CSRF Protection and GET Requests

When creating forms in Laravel usually include an @csrf token by default. If POST, PUT, PATCH, or DELETE HTTP methods do not find an @csrf token those requests will be rejected by the default Laravel application configuration. The CSRF token in Laravel is unique to the user if someone outside of your application tries to make a malicious request it will be rejected due to the missing CSRF token.

However, for GET requests the @csrf token is not available. For example if you use a GET request for a delete action the CSRF protection will not apply and a user from outside your application could use that GET request to delete application data. Therefore ensure that you do not use GET requests for actions that modify application data.

Protect Your .env File at All Costs

Your .env file contains sensitive information such as database passwords and other secrets. Do not expose it in public posts, forums, or make it publicly accessible on your server. The default Laravel .env file is in the root of the project so it should be safe if you follow the default project structure. However if you change server settings and make that folder public it could become a security risk.

Do not put your production .env file in your code repository. In order to develop applicatoin your team members only need access to an example .env file not the production credentials. Set up your server environment to contain these secrets and retrieve them at runtime or maintain the production .env file on the production server and make it accessible only to authorized personnel.

Blade and XSS Attacks

In Blade files we can escape or not escape text using the syntax {{ $var }} and {!! $var !!} respectively. For example lets say we want to display a variable containing HTML text from a controller, database or getting from an third-party application.

Using the escape text

$var = '<b>Hello, this is some HTML text</b>';

{{$var}}

<b>Hello, this is some HTML text</b>

Using non-escaped text

$var = '<b>Hello, this is some HTML text</b>';

{!! $var !!}

Hello, this is some HTML text

The non-escaped text executes the HTML within the browser which can be risky. For example:

$var = '<b>Hello, this is some HTML text<script>alert("I executed this in your browser")</script><b>';
{!! $var !!}
Execution result on the above code

This code segment will be directly executed in the browser, potentially allowing malicious users to collect data or cause harm.

Therefore, avoid using non-escaped text blocks like {!! $var !!} unless the variable is generated internally by the system. If the variable data comes from the database and is managed by users, they can insert malicious code.

Never Enable Debug Mode on UAT / Production Servers

Debug mode enabled view in laravel

On a production server, you should always set APP_DEBUG = FALSE. If you don’t, when an error occurs in your web application and it is not properly handled, the error page will be visible to any user, logged in or not.

This page can contain .env values and other sensitive information, and it will reveal that your application is built with Laravel and the specific version used. This knowledge can help a malicious user to investigate specific vulnerabilities associated with that Laravel version and gain access to your system.

Additionally, it is wise to change the default error pages in Laravel (e.g., 500 and 404 pages) and the X-Powered-By header so that users cannot easily determine that your application is built with Laravel or PHP.

Laravel’s official documentation states:

“For local development, you should set the APP_DEBUG environment variable to true. In your production environment, this value should always be false. If the variable is set to true in production, you risk exposing sensitive configuration values to your application’s end users.”

Rate Limiting

While not a direct security issue, rate limiting is a measure to prevent too many requests to your server by a single user. For instance, if someone tries to spam your server or perform a Distributed Denial-of-Service (DDoS) attack at a smaller scale, you can apply rate limiting to your application to mitigate these attacks. Rate limiting can be applied to a single route, route group, or globally, and you can customize the response and the default HTTP 429 status.

Read more about Laravel rate limiting on the official page here.

Set These Security Headers

Consider adding the following security headers to your web server or Laravel application middleware:

  • X-Frame-Options

This HTTP header is used to control whether a browser should be allowed to render a page in a <frame>, <iframe>, <embed>, or <object>. This security headder can use to prevent clickjacking attacks where an attacker could embed a site within an iframe on their malicious site and trick users into interacting with it potentially compromising their security.

Example usage

HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
X-Frame-Options: DENY

Read more in MDN

  • X-Content-Type-Options

Using the X-Content-Type-Options: nosniff header enhances the security of your web application by preventing browsers from interpreting files as a different MIME type than what is specified by the server. This helps protect against attacks such as Cross-Site Scripting (XSS) and other code injection attacks where an attacker might try to trick the browser into executing malicious content by misinterpreting the MIME type.

Example Usage

HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
X-Content-Type-Options: nosniff

Read more in MDN

  • Strict-Transport-Security (for HTTPS-only applications)

The Strict-Transport-Security (HSTS) HTTP header is used to enhance the security of a website by instructing browsers to always use HTTPS for all future requests to the site. This helps protect against various types of attacks such as man-in-the-middle attacks by ensuring that connections to the server are encrypted.

Example usage

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

Read more in MDN

  • Content-Security-Policy

The Content-Security-Policy (CSP) HTTP header is a powerful tool used to enhance the security of web applications by controlling the resources that the browser is allowed to load for a given page. It helps mitigate a variety of attacks like Cross-Site Scripting (XSS), data injection attacks and other forms of code injection attacks by specifying which sources are considered trusted for various types of content.

CSP allows you to define a set of rules that specify which types of content can be loaded and from which sources. These rules are expressed through directives each controlling a specific type of resource.

Example CSP Policy

Content-Security-Policy: 
default-src 'self';
script-src 'self' https://trustedscripts.example.com;
style-src 'self' https://trustedstyles.example.com;
img-src 'self' https://trustedimages.example.com;
connect-src 'self' https://api.example.com;
font-src 'self' https://trustedfonts.example.com;
frame-ancestors 'self'

Read more in MDN

Conclusion

Ensuring the security of your Laravel application requires attention to detail and keeping to best practices. By avoiding common mistakes like enabling debug mode in production, mishandling CSRF protection, using insecure file upload methods, and neglecting rate limiting and security headers, you can significantly enhance the security of your application.

Always stay updated with the latest Laravel documentation and continuously review and improve your security measures to protect your application and its users from potential threats.

Until next time, happy coding 🚀

--

--