The most common FiveM vulnerability is not a backdoor
Trusting a client-sent network event is more common than any deliberate backdoor, and it costs servers their economy. What an unsafe RegisterNetEvent looks like, and how to fix it.
2 min readFXScan
Deliberate backdoors get the attention. The vulnerability that actually drains servers is duller: a server-side event handler that believes what the client told it.
The shape of it
RegisterNetEvent("shop:buyItem")
AddEventHandler("shop:buyItem", function(item, price)
local src = source
local player = GetPlayer(src)
player.removeMoney(price)
player.addInventoryItem(item, 1)
end)
price arrives from the client. Any player can call this event with any
arguments, including a negative price, an item that costs nothing, or an item
they were never meant to have. Nothing in that handler is a backdoor. The
author simply forgot that a network event is user input.
The exploited version is one line:
TriggerServerEvent("shop:buyItem", "weapon_rpg", -1000000)
Why it survives review
It survives because it reads like ordinary code. There is no obfuscation, no suspicious string, nothing that a grep would catch. The bug is the absence of something - a server-side lookup of the real price - and absences are hard to notice.
It also survives because it works. The shop functions correctly for every player who is not attacking it, so it passes testing.
The fix
Never accept a value the server can determine itself:
RegisterNetEvent("shop:buyItem")
AddEventHandler("shop:buyItem", function(item)
local src = source
local definition = SHOP_ITEMS[item] -- server-owned price list
if not definition then return end -- unknown item: refuse
local player = GetPlayer(src)
if player.getMoney() < definition.price then return end
player.removeMoney(definition.price)
player.addInventoryItem(item, 1)
end)
The client now sends only which item. Price, existence and affordability are all decided server-side.
The general rule
Treat every parameter of a server-side event handler as though it were typed by someone who wants your economy. The safe pattern is:
- the client says what it wants to do,
- the server decides whether that is allowed and what it costs.
Any handler that grants money, items, weapons, jobs or group membership using a number the client supplied is a finding. FXScan raises these as a category of their own - eleven rules covering money, item, weapon, job and permission grants reached from a client payload - because in practice they cost more servers more money than the backdoors do.