Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions [core]/es_extended/server/main.lua
Original file line number Diff line number Diff line change
Expand Up @@ -272,12 +272,8 @@ function loadESXPlayer(identifier, playerId, isNew)

-- Group
if result.group then
if result.group == "superadmin" then
userData.group = "admin"
print("[^3WARNING^7] ^5Superadmin^7 detected, setting group to ^5admin^7")
else

Copy link

Copilot AI Dec 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line contains only whitespace and should be removed. The conditional logic can be simplified by directly assigning result.group to userData.group without the empty line.

Copilot uses AI. Check for mistakes.
userData.group = result.group
Copy link

Copilot AI Dec 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The indentation of this line is inconsistent with the surrounding code structure. It should be indented at the same level as the if/else block it belongs to, not nested deeper.

Suggested change
userData.group = result.group
userData.group = result.group

Copilot uses AI. Check for mistakes.
Comment on lines +275 to 276
Copy link

Copilot AI Dec 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By removing the logic that downgraded result.group == "superadmin" to "admin", any users.group value of "superadmin" is now loaded directly into userData.group and passed to CreateExtendedPlayer, which ultimately leads to add_principal identifier.<license> group.superadmin. If an attacker can influence the users.group column (e.g., via a vulnerable admin panel, misconfigured tooling, or partial DB compromise), they can grant themselves full FiveM/ACE group.superadmin rights instead of being limited to group.admin as before. To maintain a safety boundary between regular ESX admins and server superadmins, keep superadmin values rejected or downgraded here and manage group.superadmin membership only via trusted out-of-band ACL configuration.

Suggested change
userData.group = result.group
-- Prevent database-controlled escalation to superadmin.
-- Superadmin ACE rights should be managed only via trusted ACL configuration.
if result.group == "superadmin" then
userData.group = "admin"
else
userData.group = result.group
end

Copilot uses AI. Check for mistakes.
end
else
userData.group = "user"
end
Expand Down
4 changes: 0 additions & 4 deletions [core]/es_extended/server/modules/commands.lua
Original file line number Diff line number Diff line change
Expand Up @@ -510,10 +510,6 @@ ESX.RegisterCommand(
if not args.playerId then
args.playerId = xPlayer.source
end
Copy link

Copilot AI Dec 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing the guard that remapped args.group == "superadmin" to "admin" means /setgroup can now assign the superadmin group, and args.playerId.setGroup(args.group) will call add_principal identifier.<license> group.superadmin under the hood. On typical FiveM/ACE setups, group.superadmin has far broader privileges than group.admin, so any ESX admin who can run /setgroup (or an attacker who compromises such an account) can escalate to full server-level superadmin. To avoid this privilege escalation, keep superadmin assignments restricted (e.g., block superadmin here or enforce that only the console or an out-of-band ACL can grant group.superadmin).

Suggested change
end
end
if args.group == "superadmin" then
args.group = "admin"
end

Copilot uses AI. Check for mistakes.
if args.group == "superadmin" then
args.group = "admin"
print("[^3WARNING^7] ^5Superadmin^7 detected, setting group to ^5admin^7")
end
args.playerId.setGroup(args.group)
if Config.AdminLogging then
ESX.DiscordLogFields("UserActions", "/setgroup Triggered!", "pink", {
Expand Down
Loading