Overview
The CVE-2020-24941 entry describes an issue in Laravel (versions before 6.18.35 and 7.x before 7.24.0) where the $guarded property can be mishandled in requests that include JSON column nesting expressions. This results in broken object level authorization (CWE-863) because an attacker can influence which fields get mass-assigned on a target resource despite permission boundaries.
In practice, an attacker could craft a payload that updates fields the system intends to guard (for example, is_admin, role, or nested JSON keys). If a model is configured with an unguarded or poorly managed mass-assignment setup, Laravel may apply the input directly, bypassing per-object checks and letting an attacker modify another user's data.
To fix in real Laravel code, stop using mass assignment without explicit restrictions. Prefer explicit fillable fields or use Form Requests to validate and filter input. Always use authorization policies (via Gate/Policy) to enforce per-object permissions, and call $this->authorize('update', $resource) before update operations. For JSON columns, update only explicit keys or merge safely rather than mass-assigning a whole JSON field; consider handling nested updates in code rather than relying on mass assignment.
Upgrade to patched Laravel versions (6.18.35 and 7.24.0 or later), review your mass-assignment patterns, and add tests that simulate JSON-nested payloads and verify that updates are blocked when not authorized.
Affected Versions
Laravel 6.x before 6.18.35 and Laravel 7.x before 7.24.0
Code Fix Example
Laravel API Security Remediation
Vulnerable pattern:
// app/Models/User.php
class User extends \Illuminate\Database\Eloquent\Model {
protected $guarded = [];
}
// app/Http/Controllers/UserController.php
class UserController extends Controller {
public function update(Request $request, $id) {
$user = User::findOrFail($id);
// Attacker can set admin flag via JSON payload
$user->update($request->all());
return response()->json($user);
}
}
Fix:
// app/Models/User.php
class User extends \Illuminate\Database\Eloquent\Model {
protected $fillable = ['name', 'email', 'profile']; // restrict mass assignment
}
// app/Http/Controllers/UserController.php
class UserController extends Controller {
public function update(Request $request, $id) {
$user = User::findOrFail($id);
// Enforce authorization at policy level
$this->authorize('update', $user);
// Only update whitelisted fields
$user->update($request->only(['name', 'email', 'profile']));
return response()->json($user);
}
}
// Optional policy example (simplified):
// app/Policies/UserPolicy.php
class UserPolicy {
public function update(User $auth, User $model) {
return $auth->id === $model->id;
}
}