> For the complete documentation index, see [llms.txt](https://sbscripts.gitbook.io/sb-scripts/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://sbscripts.gitbook.io/sb-scripts/sb-anticheat/safe-events.md).

# Safe Events

Mod menus can fire any server event they like, for example your boss menu's `withdrawMoney`. Safe events only accept a protected event if it came from your own client code.

It has two parts.

### 1. Client wrapper

`client/safeevents.lua` wraps `TriggerServerEvent`. Each time a script calls it, the wrapper first sends a short `sbanticheat:server:validateEvent` message naming the event, waits 250 ms, then sends the real event. An executor that fires the event directly skips the wrapper, so the heads-up never reaches the server.

Add it to the `fxmanifest.lua` of each resource whose events you want protected. It must be the **first** client script:

```lua
client_scripts {
    '@sbanticheat/client/safeevents.lua',   -- must be above everything else
    'client/main.lua',
}
```

Because of the 250 ms wait, only use it on resources that fire events occasionally, such as menus and banking. Don't use it on events that fire every frame.

### 2. Server list

`shared/safeevents.lua`:

```lua
SB.safeEvents = {
    enabled    = true,
    punishment = "log",   -- "ban" | "kick" | "log"

    protectedEvents = {
        ["qb-bossmenu:server:withdrawMoney"] = true,
        ["qb-bossmenu:server:depositMoney"]  = true,
    },
}
```

For every event set to `true`, the server expects the heads-up from that same player just before the event arrives. If it doesn't come, the event is cancelled, a `SafeEventViolation` is logged, and the player gets the `punishment` set here, not the global one. Set an event to `false` to stop protecting it.

Safe events is off by default. Start with `"log"` so you can confirm your legitimate scripts aren't being caught, then switch to `"kick"` or `"ban"`.
