Skip to main content
UgCore assumes any client can be modified. Protection comes in four layers. Each layer MUST work even if the others fail.

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.
Excess traffic is dropped before any handler runs.

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 with UgCore.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. Lock entity creation from clients with FXServer’s sv_entityLockdown. Sessions created by UgCore already use strict lockdown. Check the Cfx documentation for current values before setting it server-wide.