Client and server in depth · Lesson 1/4 · 10 min

Secure events: don't trust the client

Any player can fire your network events with whatever data they want. Learn to validate them.

A RegisterNetEvent is an open door: any player can fire it from their client with whatever arguments they please. If you don't validate, you're handing out cheats. In QBCore this is exactly as dangerous as in ESX.

The typical mistake (vulnerable)

lua
-- ❌ BAD: trusts the amount and price sent by the client
RegisterNetEvent('tienda:server:vender', function(cantidad, precio)
  local Player = QBCore.Functions.GetPlayer(source)
  Player.Functions.AddMoney('cash', cantidad * precio) -- infinite money
end)

Vulnerable

Here a cheater sends cantidad=99999 and precio=99999 and gets rich. The price and the logic must NEVER come from the client.

The secure version

lua
RegisterNetEvent('tienda:server:vender', function(itemName, cantidad)
  local src = source
  local Player = QBCore.Functions.GetPlayer(src)
  if not Player then return end

  -- 1) validate types and ranges
  cantidad = tonumber(cantidad)
  if not cantidad or cantidad < 1 or cantidad > 100 then return end

  -- 2) the PRICE is decided by the server, not the client
  local precio = Config.Precios[itemName]
  if not precio then return end

  -- 3) check that the player ACTUALLY HAS what they claim to sell
  local item = Player.Functions.GetItemByName(itemName)
  if not item or item.amount < cantidad then return end

  Player.Functions.RemoveItem(itemName, cantidad)
  Player.Functions.AddMoney('cash', precio * cantidad, 'venta-' .. itemName)
end)

Full validation

  • Validate the type and range of each argument (tonumber, limits).
  • Prices, rewards and logic come from Config or DB on the server, never from the client.
  • Check that the player has/can do what they ask (GetItemByName, money, job, distance).

Practice what you learned

0/3
Test

¿Por qué es peligroso un RegisterNetEvent que se fía de los datos del cliente?

Corrige el error

Este evento de venta confía en el precio que manda el cliente (dinero infinito). Arréglalo: el precio debe salir de Config en el servidor, no de los argumentos.

Este código tiene un fallo:

1RegisterNetEvent('tienda:server:vender', function(cantidad, precio)
2 local Player = QBCore.Functions.GetPlayer(source)
3 Player.Functions.AddMoney('cash', cantidad * precio)
4end)

Reescríbelo corregido:

Pista

Quita 'precio' de los argumentos, recibe itemName, y léelo con Config.Precios[itemName] dentro del servidor.

Rellena los huecos

Completa la primera línea del cuerpo del evento: guarda el source y obtén el Player, comprobando que existe.

1RegisterNetEvent('tienda:server:vender', function(itemName, cantidad)
2 local src = source
3 local Player = QBCore.Functions.GetPlayer(src)
4 if not then return end
5end)
Pista

El jugador puede no estar cargado; el guard corta la ejecución si GetPlayer devolvió nil.

Challenge: code it yourself

Take an event that gives an item to the player and harden it: validate the amount (1-10) and that the item is in a list of allowed Config items.

Write it yourself in your editor (VS Code) and test it on your server. You learn here by doing it, not by copying.

See hint

tonumber + check range + Config.ItemsPermitidos[item] before AddItem.

Escribe aquí tu solución:

How was this lesson?