DEV Community

Cover image for Laravel's `fillable property` and the Hidden Danger to Your Business App
Claude Fassinou
Claude Fassinou

Posted on

Laravel's `fillable property` and the Hidden Danger to Your Business App

Laravel is a powerful PHP framework, and its Eloquent ORM makes database interactions a breeze. However, a common pitfall involving the $fillable property can lead to a critical security flaw known as a Mass Assignment Vulnerability, potentially compromising your entire application.

What is Mass Assignment?

Mass assignment is the practice of populating a model with an array of user input, usually from a form submission, in a single go. In Laravel, this often looks like:

// Populating a model with ALL request data
User::create(\$request->all()); // ๐Ÿ‘ˆ DANGER ZONE!
Enter fullscreen mode Exit fullscreen mode

This is convenient, but it's dangerous if you don't control which attributes are allowed to be set this way.

The Role of \$fillable

The $fillable property in a Laravel model is your white-list for mass assignment. It specifies an array of columns that are safe to be filled using methods like create(), update(), or fill().

If an attribute is not in the $fillable array, Laravel's security layer will prevent it from being set via mass assignment.

The Business Danger: Unrestricted Access

This code illustrates the danger:

  1. Vulnerable Model: The User model has a sensitive column, is_admin, included in the $fillable array.

    // In User.php
    protected \$fillable = [
        'name',
        'email',
        'password',
        'is_admin', // ๐Ÿ‘ˆ THE FLAW
    ];
    
  2. Vulnerable Controller: The application blindly accepts and assigns all validated request data to the model.

    // In TestController.php
    User::create(\$request->all()); 
    

A malicious user can simply inject an is_admin field into their registration form data. Because the controller uses create(\$request->all()) and is_admin is in $fillable, the application will happily set the user's is_admin attribute to true (or 1).

๐Ÿ”ฅ The Result: A standard user can instantly become an Administrator, gaining unauthorized access to sensitive data, control panels, and potentially damaging your entire system and business integrity.


The Solution: Always Restrict \$fillable

To protect your business, always adhere to this simple rule:

NEVER include sensitive, high-privilege columns like is_admin, role, api_token, or balance in your model's \$fillable property.

The Safe Code Fix:

  1. Remove the sensitive field from $fillable:

    // The SECURE User.php
    protected \$fillable = [
        'name',
        'email',
        'password',
        // 'is_admin' is GONE! โœ…
    ];
    
  2. Explicitly handle sensitive fields (if needed): If you need to set is_admin or another protected field, do it explicitly, line by line, only after checking authorization.

    // The SECURE Controller code
    \$validatedData = \$request->validate([...]);
    
    \$user = User::create(\$validatedData); 
    
    // Set protected fields ONLY if an authorized admin is doing it.
    // e.g., if (auth()->user()->isAdmin()) { \$user->is_admin = 1; \$user->save(); }
    

Protect your application by being meticulous with your $fillable arrays!

I am Claude Fassinou, Software developer, and Code reviewer.

Top comments (0)