Skip to Content
SecurityAnti-Cheat Basics
Open in ChatGPTOpen in Claude

Anti-Cheat Basics

Understanding anti-cheat systems and false positives.

Concepts

Never accept results from the client

A modified client can trigger any server event with any arguments. Let the client ask for an action and have the server read every value that matters (position, inventory, job, cooldown) itself. Do not accept coordinates, prices, amounts or targets from the client and only range-check them.

-- server.lua: the client only says "I am at checkpoint N" local CHECKPOINTS = { vector3(215.8, -810.1, 30.7), vector3(-1037.6, -2737.6, 20.2), } RegisterNetEvent('myresource:claimCheckpoint', function(index) local src = source if type(index) ~= 'number' or index % 1 ~= 0 then return end local target = CHECKPOINTS[index] if not target then return end local ped = GetPlayerPed(src) if ped == 0 then return end -- The server's view of the position, not a client-supplied value. if #(GetEntityCoords(ped) - target) > 5.0 then print(('[myresource] %s claimed checkpoint %d from too far away'):format(src, index)) return end -- Grant the reward here, using server-side state only. end)

The server position is the last state the client synced, so it can lag slightly behind. Use a tolerance that fits your gameplay and log rejections instead of punishing them immediately. See secure events for the full checklist.

Rate limiting

Keep the limit per player. A single shared timestamp lets one player lock everyone else out of the feature.

local lastAction = {} RegisterNetEvent('myresource:action', function() local src = source local now = GetGameTimer() if lastAction[src] and now - lastAction[src] < 1000 then return -- too fast end lastAction[src] = now -- Process action end) -- Server IDs are reused after a disconnect (immediately on Enhanced), so -- forget per-player state when the player leaves. AddEventHandler('playerDropped', function() lastAction[source] = nil end)

Block client-side entity creation

With OneSync, clients can create networked entities unless you lock that down. Use sv_entityLockdown or per-bucket SetRoutingBucketEntityLockdownMode and create entities from server code instead. See OneSync.

False Positives

Common causes:

  • Network lag
  • Script bugs
  • Legitimate edge cases

Best Practices

  • Log suspicious activity
  • Review before banning
  • Provide appeals process
  • Monitor false positive rate