Skip to content

Commit e0c5e09

Browse files
committed
fix(model): remove role and api_token from User $fillable
These sensitive fields were mass-assignable, enabling privilege escalation if any controller passed unfiltered request data to User::update() or User::create(). All call sites that previously set role via mass assignment now use direct property assignment.
1 parent ecef4ff commit e0c5e09

4 files changed

Lines changed: 14 additions & 4 deletions

File tree

app/Console/Commands/UserCreate.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ public function handle(DiscourseService $discourseService): void
101101
'name' => $name,
102102
'email' => $email,
103103
'password' => Hash::make($password),
104-
'role' => $role,
105104
'recovery' => substr(bin2hex(openssl_random_pseudo_bytes(32)), 0, 24),
106105
'recovery_expires' => strftime('%Y-%m-%d %X', time() + (24 * 60 * 60)),
107106
'calendar_hash' => Str::random(15),
@@ -118,6 +117,9 @@ public function handle(DiscourseService $discourseService): void
118117

119118
if ($user)
120119
{
120+
$user->role = $role;
121+
$user->save();
122+
121123
$this->info("User created {$user->name} (#{$user->id})");
122124
$this->info("Role: {$this->getRoleName($user->role)}");
123125

app/Http/Controllers/Auth/RegisterController.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Illuminate\Routing\Controllers\HasMiddleware;
66
use Illuminate\Routing\Controllers\Middleware;
77
use App\Http\Controllers\Controller;
8+
use App\Models\Role;
89
use App\Models\User;
910
use Illuminate\Foundation\Auth\RegistersUsers;
1011
use Illuminate\Support\Facades\Hash;
@@ -62,11 +63,13 @@ protected function create(array $data): User
6263
'name' => $data['name'],
6364
'email' => $data['email'],
6465
'password' => Hash::make($data['password']),
65-
'role' => 4,
6666
'recovery' => substr(bin2hex(openssl_random_pseudo_bytes(32)), 0, 24),
6767
'recovery_expires' => strftime('%Y-%m-%d %X', time() + (24 * 60 * 60)),
6868
]);
6969

70+
$user->role = Role::RESTARTER;
71+
$user->save();
72+
7073
Session::createSession($user->id);
7174

7275
return $user;

app/Http/Controllers/UserController.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1007,7 +1007,6 @@ public function postRegister(Request $request, $hash = null): RedirectResponse
10071007
'name' => $request->input('name'),
10081008
'email' => $request->input('email'),
10091009
'password' => Hash::make($request->input('password')),
1010-
'role' => $role,
10111010
'recovery' => substr(bin2hex(openssl_random_pseudo_bytes(32)), 0, 24),
10121011
'recovery_expires' => strftime('%Y-%m-%d %X', time() + (24 * 60 * 60)),
10131012
'country_code' => $request->input('country'),
@@ -1017,6 +1016,9 @@ public function postRegister(Request $request, $hash = null): RedirectResponse
10171016
'calendar_hash' => Str::random(15),
10181017
'username' => '',
10191018
]);
1019+
1020+
$user->role = $role;
1021+
$user->save();
10201022
}
10211023

10221024
$user->generateAndSetUsername();

app/Models/User.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,11 @@ class User extends Authenticatable implements Auditable, HasLocalePreference
4040
*
4141
* @var array
4242
*/
43+
// Note: `role` and `api_token` are intentionally excluded from $fillable.
44+
// They must be set via direct assignment ($user->role = X; $user->save())
45+
// to prevent privilege escalation via mass assignment (security: C2/M1).
4346
protected $fillable = [
44-
'name', 'email', 'password', 'role', 'recovery', 'recovery_expires', 'language', 'repair_network', 'location', 'age', 'gender', 'country_code', 'newsletter', 'invites', 'biography', 'consent_future_data', 'consent_past_data', 'consent_gdpr', 'number_of_logins', 'latitude', 'longitude', 'last_login_at', 'api_token', 'access_group_tag_id', 'calendar_hash', 'repairdir_role', 'mediawiki', 'username', 'external_user_id', 'external_username',
47+
'name', 'email', 'password', 'recovery', 'recovery_expires', 'language', 'repair_network', 'location', 'age', 'gender', 'country_code', 'newsletter', 'invites', 'biography', 'consent_future_data', 'consent_past_data', 'consent_gdpr', 'number_of_logins', 'latitude', 'longitude', 'last_login_at', 'access_group_tag_id', 'calendar_hash', 'repairdir_role', 'mediawiki', 'username', 'external_user_id', 'external_username',
4548
];
4649

4750
/**

0 commit comments

Comments
 (0)