Layer 1: payload validation
Every net event and callback has a schema. No schema, no registration. Schemas are bounded: strings, arrays and maps MUST declare a maximum, so a client cannot send a megabyte where a name was expected. See Schemas.Layer 2: rate limits
- Global budget: one budget per player across every UgCore net event and callback, from every resource. 40 requests per second by default.
- Per event: each registration declares its own
rate. - Concurrency: at most 4 callbacks in flight per player.
Layer 3: server authority
Intent, not results
A client asks to buy an item. The server decides the price, checks the money and gives the item. A client never sends an amount to add.
Positions from the ped
UgCore.Guard.IsNear(source, coords, maxDistance) reads the ped position on the server. Client coordinates are never trusted.Identity from source
The player is always the event
source. Never read a player id or identifier from arguments.Server-only state
Statebags are written by the server only. Cooldowns are enforced on the server.
Layer 4: Guard
Every rejection adds to the player’s score. Your own checks report withUgCore.Guard.Flag. Scores decay; thresholds warn, kick or ban. See Guard.
What never reaches a client
- Stack traces. Handlers that crash answer
internal_error. - Which check failed. Kick and ban messages are generic.
- Validation details. They go to server logs, without echoing large input.
Spoofed core events
ug-core:* events are only accepted from ug-core itself. Another resource, or a client through a misconfigured net event, cannot fake them. See Events.
Recommended server settings
Lock entity creation from clients with FXServer’ssv_entityLockdown. Sessions created by UgCore already use strict lockdown. Check the Cfx documentation for current values before setting it server-wide.