I keep seeing posts that recommend client-side checks for anything sensitive. This is a quick demo of why that's dangerous, with a concrete example anyone can reproduce in 5 minutes.
The setup
Imagine a script that does this:
RegisterNetEvent('police:requestArrest', function(targetId)
local src = source
-- Server check: is the requester police?
if not isPolice(src) then return end
-- Cuff target
TriggerClientEvent('player:cuff', targetId)
end)
You think you're safe because of isPolice(src).
The exploit
A modded client doesn't go through requestArrest. They directly call:
TriggerServerEvent('police:requestArrest', someVictimId)
No isPolice check on the trigger, only on the receiver. Wait — that should still be caught, right? It is.
But this:
RegisterNetEvent('player:cuff', function()
-- play cuff animation
SetEnableHandcuffs(PlayerPedId(), true)
end)
The client emits TriggerServerEvent('police:requestArrest', source) to source of someone who is in their game session. The server still rejects it. Good.
Where it actually breaks
The dangerous version:
RegisterNetEvent('player:cuff') -- BAD: this is callable by anyone
AddEventHandler('player:cuff', function()
SetEnableHandcuffs(PlayerPedId(), true)
end)
A modded client calls TriggerServerEvent('player:cuff') and triggers their own server's broadcast. Or worse, a script broadcasts TriggerClientEvent('player:cuff', -1) and every player gets cuffed because the receiver event is unauthenticated.
The fix
Treat every RegisterNetEvent on the client as if a malicious server could trigger it. Always verify origin:
RegisterNetEvent('player:cuff', function()
-- 'source' on client = the server, but we got the data, not WHO sent it
-- so we have to trust the authority of OUR server to not broadcast bad events
SetEnableHandcuffs(PlayerPedId(), true)
end)
There's no client-side cure here. The fix is: don't put authority logic in events that can be broadcast. Use stateBags with replicated=true and a server authority, or use server-issued tokens.
Client-side AC is dead. Long live server-side state.