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!
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:
-
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 ];
-
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:
-
Remove the sensitive field from
$fillable
:
// The SECURE User.php protected \$fillable = [ 'name', 'email', 'password', // 'is_admin' is GONE! โ ];
-
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)