Laravel Mass Assignment Vulnerability: How to Protect Eloquent Models with $fillable and $guarded
Eloquent models without $fillable or $guarded allow attackers to set any database column through request input, including is_admin, role, or email_verified_at.
The Problem
Mass assignment occurs when an Eloquent model accepts all request input without restriction. If a model lacks $fillable or $guarded, an attacker can add extra fields to a form submission — like is_admin=1 or role=superadmin — and those values get written directly to the database. This is one of the most common Laravel vulnerabilities and the reason the framework includes mass assignment protection by default.
How to Fix
-
1
Add $fillable to every Eloquent model
Explicitly list the columns that can be mass-assigned:
class User extends Model { protected $fillable = [ 'name', 'email', 'password', ]; }Never include sensitive columns like is_admin, role, email_verified_at, or balance in $fillable.
-
2
Or use $guarded as a blocklist
If you prefer a blocklist approach, set $guarded to protect specific columns:
class User extends Model { protected $guarded = [ 'id', 'is_admin', 'role', 'email_verified_at', ]; }Warning: $guarded = [] (empty array) disables all protection and is equivalent to having no mass assignment guard at all. Never use this in production. -
3
Validate and filter input before creating models
Even with $fillable, always validate input first:
$validated = $request->validate([ 'name' => 'required|string|max:255', 'email' => 'required|email|unique:users', ]);User::create($validated);
Using $request->validate() returns only the validated fields, providing a second layer of protection beyond $fillable. -
4
Audit existing models for missing protection
Search your codebase for models without mass assignment protection:grep -rL 'fillable\|guarded' app/Models/This lists all model files that don't contain either $fillable or $guarded. Fix each one before deploying.
How to Verify
Test by sending an unexpected field in a request:
curl -X POST https://yourapp.com/api/users \
-d 'name=Test&email=test@test.com&is_admin=1'
Then check the database — the is_admin column should not be set to 1. Also run the Stackshield scanner to verify: php artisan stackshield:scan --check=SS001
Prevention
Use a Pint or PHPStan rule to flag models without $fillable. Add mass assignment checks to your CI pipeline. Prefer $fillable (allowlist) over $guarded (blocklist) for stronger defaults. Use StackShield to continuously monitor for unprotected models.
Frequently Asked Questions
Is $guarded = [] ever acceptable?
Almost never. Some developers use it during rapid prototyping, but it should never reach production. If you need maximum flexibility, use $guarded with an explicit list of protected columns rather than an empty array.
Does Form Request validation prevent mass assignment?
Partially. Form Requests validate input types and values, but the validated data still goes through Eloquent mass assignment. Both layers are needed: validation ensures correct data types, $fillable ensures only allowed columns are written.
What about Model::unguarded() in seeders?
Model::unguarded() temporarily disables mass assignment protection and is common in database seeders. This is safe in seeders since they run in controlled environments, but never use it in controllers, jobs, or any code that handles user input.
Related Security Terms
Related Guides
How to Prevent SQL Injection in Laravel
SQL injection vulnerabilities in raw queries and improper Eloquent usage can expose your database. Learn how to write secure queries.
Laravel XSS Prevention Guide: Blade Escaping, {!! !!} Risks & CSP Headers
Prevent cross-site scripting in Laravel. Learn when {!! !!} is safe, how to sanitize HTML input, encode output in Blade templates, and add Content Security Policy headers.
Fix Missing CSRF Protection in Laravel: @csrf, VerifyCsrfToken & API Routes
Laravel forms without @csrf tokens are vulnerable to cross-site request forgery. Learn how to add CSRF protection, configure VerifyCsrfToken exceptions, and handle CSRF for API routes.
Detect This Automatically with StackShield
StackShield continuously monitors your Laravel application from the outside and alerts you when security issues are found. No installation required.
Start Free Trial