Protect your script

Built-in whitelist

How SantiAuth embeds the whitelist into your script, and what that means for security.

On this page

Not a loader — a whitelist inside your file

SantiAuth does not download your source at runtime. Every script you obfuscate in the dashboard gets the whitelist embedded — the backend builds one file:

text
┌──────────────────── file the player runs ────────────────────┐
│ SA_INIT_SCRIPT function   (optional, not obfuscated)         │
│ ┌──────────────────── obfuscated ──────────────────────────┐ │
│ │ local SantiAuth = <client>                               │ │
│ │ SantiAuth.script_id = "<id>"     -- injected for you     │ │
│ │ SantiAuth.run_whitelist()        -- kicks without a key  │ │
│ │ -- your script                                           │ │
│ └──────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘

Because of that:

  • Your source never travels over the network. The server only answers with a signed activation; it never sends code.
  • No key, no code. run_whitelist() kicks the player before the first line of your script runs.
  • SantiAuth is a local variable of the chunk — it can't be replaced through getgenv().
  • SA_* variables are written into your script's own environment, so other scripts in the executor can't see them.

Where the key comes from

The whitelist looks for a key in this order:

  1. The key passed to check_key(key).
  2. script_key in your script's environment.
  3. getgenv().script_key.

The usual way is to set it right before the loadstring:

lua
script_key = "PASTE-YOUR-KEY-HERE"
loadstring(game:HttpGet("https://api.santiauth.com/api/loader/v4/script/<script-id>"))()

What happens on execution

  1. 1

    Executor → SantiAuth API

    Requests your script

  2. 2

    SantiAuth API → Executor

    Public stub (no grant yet)

  3. 3

    Executor → SantiAuth API

    Stub sends script_key

  4. 4

    SantiAuth API → Executor

    2-minute grant, then the protected file

  5. 5

    Executor → SantiAuth API

    Validates the key, opens a signed session

  6. 6

    SantiAuth API → Executor

    Encrypted, signed activation

  7. 7

    Executor

    Sets SA_* and runs your code

  8. 8

    Executor → SantiAuth API

    Heartbeat every 20 seconds

  1. Download — the loader URL never hands out the protected file without a valid key. Without a download grant it returns a small public stub: it runs your SA_INIT_SCRIPT (if any), checks script_key, gets a 2-minute grant and only then downloads the real file. A missing or bad key kicks right here, before anything of your script is downloaded.
  2. Validate — the key is checked over HTTPS: exists, not banned, not expired, HWID matches (or is bound for the first time), and the script belongs to the key's owner.
  3. Start — the client opens a one-time session signed with a per-session secret, and sends an integrity report about the executor.
  4. Activate — the server replies with an encrypted, signed activation. A hooked request can't forge it.
  5. Run — SA_* variables are set and your code runs.
  6. Heartbeat — every 20 seconds the session is re-checked. A revoked or expired key ends it.

Updating the client

When SantiAuth ships a new client version, scripts you obfuscated earlier still contain the old copy. Press Re-obfuscate on the script in Obfuscation to rebuild it with the current client — the loader URL stays the same.