Skip to content

Reference

Rule reference

Guardian currently runs 26 rules. Each rule is versioned: when a rule changes, its version changes, so you can tell whether a new finding comes from your code or from the rule.

Monetization · 7

  • Developer products are sold but no purchase handler is set

    monetization.process-receipt.missing@1

    The game prompts developer product purchases but no enabled server script assigns MarketplaceService.ProcessReceipt.

  • ProcessReceipt is assigned more than once

    monetization.process-receipt.multiple@1

    Only one ProcessReceipt callback can be active; later assignments replace earlier ones.

  • ProcessReceipt is assigned on the client

    monetization.process-receipt.client@1

    ProcessReceipt only works on the server. A client assignment never runs.

  • Purchase handler never returns PurchaseGranted

    monetization.process-receipt.never-granted@1

    A ProcessReceipt handler that never returns PurchaseGranted leaves every purchase unfinished.

  • Purchase handler cannot ask Roblox to retry

    monetization.process-receipt.no-retry-path@1

    The handler never returns NotProcessedYet, so failures are reported to Roblox as success.

  • Purchase handler does not track PurchaseId

    monetization.process-receipt.not-idempotent@1

    Roblox can deliver the same receipt more than once. Handlers should record PurchaseId.

  • Game pass ownership is only checked on the client

    monetization.game-pass.client-only-check@1

    Perks granted from client-side ownership checks can be unlocked by exploiters.

Security · 8

  • Module loaded from the Roblox website by asset id

    security.require-by-asset-id@1

    require(assetId) downloads code that is not in your place and can change at any time.

  • Code is compiled at runtime with loadstring

    security.loadstring@1

    loadstring runs arbitrary text as code and is a common backdoor and exploit vector.

  • Credential stored in a script

    security.hardcoded-secret@1

    Secrets in source travel with every copy of the place file.

  • Server applies a value sent by the client

    security.remote-trusts-client-value@1

    Remote handlers must not write client-supplied amounts into player state.

  • Script appears to be obfuscated

    security.obfuscated-source@1

    Obfuscated code cannot be reviewed and is a strong indicator of a backdoor.

  • Function environments are read or replaced

    security.function-environment@1

    getfenv and setfenv are rarely needed and are frequently used to hide malicious code.

  • Remote can spam DataStore requests

    security.remote-triggers-datastore@1

    A client can fire this remote as often as it likes, and each call makes a DataStore request.

  • Server waits on InvokeClient

    security.server-invokes-client@1

    InvokeClient yields until the client answers, and the client controls the answer.

Reliability · 4

  • DataStore requests are not wrapped in pcall

    reliability.datastore-without-pcall@1

    DataStore calls are network requests that can fail and throw.

  • Player data may be lost when a server shuts down

    reliability.no-bind-to-close@1

    Games that save to DataStores should save remaining players in game:BindToClose.

  • Player data saved with SetAsync

    reliability.datastore-setasync-player-data@1

    SetAsync overwrites whatever is stored. UpdateAsync lets the save check the stored value first.

  • Player data has no session lock

    reliability.no-session-locking@1

    Loads on join and saves on leave with no lock, so two servers can hold the same player at once.

Performance · 5

  • Infinite loop never yields

    performance.loop-without-yield@1

    `while true do` without a wait freezes the script, and on the client the whole game.

  • DataStore called every frame or on touch

    performance.datastore-per-frame@1

    DataStore requests inside Heartbeat, Stepped or Touched handlers hit the request limit.

  • Connection made per player is never disconnected

    performance.connection-leak-per-player@1

    Connecting to a global signal each time a player or character spawns leaks a connection every time.

  • Per-player table is never cleared

    performance.player-table-not-cleared@1

    Entries keyed by player are added but never set to nil when the player leaves.

  • Remote fired every frame

    performance.remote-fired-every-frame@1

    Firing a RemoteEvent from Heartbeat or a tight loop sends a packet per frame per player.

Quality · 2

  • Client script changes leaderstats

    quality.client-writes-leaderstats@1

    Changes made by LocalScripts do not replicate to the server.

  • Deprecated wait, spawn or delay

    quality.deprecated-scheduler-globals@1

    The legacy scheduling globals are throttled; the task library replaces them.