Parent : [[INDEX-FIVEM-BACKEND]]
Anti-Pattern : Client-Side Validation Only (FiveM)
Erreur à éviter
Faire confiance aux données envoyées par le client sans validation serveur. Les clients peuvent être modifiés (cheat menus, mods, injecteurs).
Exemple incorrect
-- ❌ DANGER - Validation uniquement côté client
-- client.lua
RegisterCommand('givemoney', function(source, args)
local amount = tonumber(args[1])
if amount > 0 and amount < 10000 then -- Validation client seule
TriggerServerEvent('giveMoney', amount)
end
end)
-- server.lua (FAIBLE)
RegisterNetEvent('giveMoney')
AddEventHandler('giveMoney', function(amount)
local src = source
-- PAS DE VÉRIFICATION !
Player(src).addMoney(amount) -- Le cheater peut envoyer n'importe quel montant
end)
Exploitation possible
-- Cheat menu peut injecter :
TriggerServerEvent('giveMoney', 999999999) -- Bypass client validation
TriggerServerEvent('giveMoney', -1000000) -- Negative = dupe glitch
TriggerServerEvent('revivePlayer', targetId, true) -- Force revive anyone
Bonne pratique
-- ✅ CORRECT - Validation côté serveur OBLIGATOIRE
-- server.lua
RegisterNetEvent('wasabi_ambulance:giveMoney')
AddEventHandler('wasabi_ambulance:giveMoney', function(amount)
local src = source
-- 1. Validation du type
amount = tonumber(amount)
if not amount then
print(('[^3SECURITY^7] Player %s tried to send invalid amount'):format(src))
return
end
-- 2. Validation des limites
if amount <= 0 or amount > 10000 then
print(('[^3SECURITY^7] Player %s tried to give invalid amount: %s'):format(src, amount))
-- Optional: ban/kick via anticheat
return
end
-- 3. Validation contextuelle (a-t-il le droit?)
if not IsPlayerAuthorized(src, 'give_money') then
print(('[^1SECURITY^7] Player %s unauthorized action'):format(src))
return
end
-- 4. Validation de l'état (peut-il vraiment?)
if not IsPlayerNearBank(src) then
exports['wasabi_ems']:Notify(src, 'error', 'Vous devez être à la banque')
return
end
-- 5. Exécution
Player(src).addMoney(amount)
LogTransaction(src, amount, 'give')
end)
Pattern de validation robuste
-- Utilitaire de validation
function ValidatePlayerAction(playerId, action, data)
-- Check 1: Player exists
if not DoesPlayerExist(playerId) then return false, 'Player not found' end
-- Check 2: Rate limiting
if IsPlayerRateLimited(playerId, action) then
return false, 'Rate limited'
end
-- Check 3: Authorization
if not IsPlayerAuthorized(playerId, action) then
TriggerEvent('wasabi_anticheat:suspicious', playerId, 'unauthorized_'..action)
return false, 'Unauthorized'
end
-- Check 4: Data validation
if not ValidateData(data, action) then
return false, 'Invalid data'
end
return true
end
Règle d'or
Never trust the client. Validate everything on the server.
Checklist de validation serveur
- Type checking (tonumber, tostring)
- Range validation (min/max)
- Authorization (permissions/jobs)
- State validation (peut-il faire ça maintenant?)
- Distance check (est-il proche?)
- Rate limiting (anti-spam)
- Logging (pour audit)
Références
- CFX Security Guidelines
- ESX/QB-Core security best practices
- Pattern WASABI : Validation des actions médicales