Note: This security patch only affects applications using the $guarded
property on models. In addition, applications that set $guarded
to []
or ['*']
are not affected by the bug described in this post.
Today we are releasing a follow-up to yesterday's security patches. Today's patch secures another subtle security issue when using $request->all()
to update Eloquent's models that use the $guarded
property.
When listing individual columns in the $guarded
property, any columns that are not included in the list can be updated via mass assignment. This is expected behavior. However, unexpected updates may happen if requests are crafted to contain JSON column nesting expressions ({"foo->bar": "value"}
). Even if the JSON foo
column is guarded, this expression could update the bar
JSON key within the column (because foo->bar
is not listed in the guarded clause).
Today's patch fixes this and other potential unexpected behaviors by comparing the column that is being updated with an actual list of database columns that exist on the database table. We retrieve this column list using Laravel's schema inspection facilities that already existed in the framework. Note that this will introduce one extra database query to retrieve the column listing when attempting to mass assign attributes to a model that is using the $guarded
property. If the $guarded
property is empty or is set to ['*']
the extra query is unnecessary and will not be executed. Applications that use $fillable
are already protected by default and do not require us to confirm the column's validity.
As a personal recommendation, I recommend always using $fillable
instead of $guarded
. In general, $fillable
is a safer approach to mass assignment protection because you are forced to list any new columns added to the database to the $fillable
array. In contrast, you may easily forget to add a new column to a $guarded
array, leaving it open for mass assignment by default.