Roblox security guides
28 problems that show up in Roblox games, what an exploiter could do with each one, and how to fix it in Luau. They're the same checks Luaudit gives your AI when it audits your game.
Remote events
How the server handles RemoteEvents, UnreliableRemoteEvents and RemoteFunctions. Every remote is a door into the server, and an exploiter can fire it at any time with any arguments.
When a remote sends a price, reward or damage value, the client decides it. How to send only the player's choice and look everything else up on the server.
How to range-check numbers sent to RemoteEventscriticalA typeof check alone lets negative numbers, NaN and infinity through. How to write range checks for amounts, quantities and stock that reject all three.
How to validate RemoteEvent arguments in RobloxcriticalEvery argument after the player in OnServerEvent comes from the client. How to check types with typeof, use allowlists and reject bad values before they reach saved data.
How to check Instances sent through RemoteEventscriticalChecking an Instance's class doesn't prove the player may use it. How to check a tool, part or model sent by the client belongs to that player.
How to rate limit RemoteEvents in RobloxwarningA remote that spawns parts, plays effects or calls data stores can be fired far faster than any button. How to add a per-player cooldown on the server.
Why the server shouldn't wait on InvokeClientwarningRemoteFunction:InvokeClient lets a client stall or break server code. How to replace it with two RemoteEvents and a timeout the server controls.
Server validation
Whether the server checks that an action is allowed before it happens: that the player owns or has unlocked what they picked, hasn't claimed a reward already, is close enough to what they're using and could really have landed a hit, and that nothing can slip in between a check and the change it guards.
Checking that an id exists isn't the same as checking the player has it. How to check pets, skins, classes and zones against the player's own data.
How to stop daily rewards and codes being claimed twicecriticalDaily rewards, promo codes and quest prizes that pay out again on every call or rejoin. How to record claims in saved data before paying.
How to validate combat hits on the server in RobloxcriticalIf the client reports hits and the server just applies damage, hits can land from anywhere. How to check range, cooldowns and ranged shots on the server.
How to stop yields letting players claim or spend twicecriticalA yield between a check and the change it guards lets the same remote pass the check twice. How to order handlers so the change happens first.
How to add server-side distance checks in RobloxwarningChests, shops and sell pads that work from anywhere on the map. How to check on the server that the player's character is close enough to use them.
Data stores
How the game loads and saves with DataStoreService: what happens when a load or save fails, whether two servers can hold the same player's data at once, whether servers can overwrite each other's writes, and whether the client can choose which key the server reads or writes.
Building a data store key from a user id or slot the client sent lets one player read or overwrite another's data. How to build keys on the server.
How to stop a failed data store load wiping player datacriticalTreating a failed load as a new player hands out default data, which is then saved over the real data. How to keep failed loads apart from new players.
How to session-lock player data in RobloxcriticalWithout a session lock, two servers can hold the same player's data and the later save wins. How session locking with UpdateAsync works.
How to use UpdateAsync for values many servers changecriticalGetAsync followed by SetAsync lets two servers overwrite each other's changes to a bank, counter or limited stock. How to use UpdateAsync and IncrementAsync instead.
How to save player data when a Roblox server shuts downwarningSaving only in PlayerRemoving can lose data when a server closes. How to use BindToClose to wait for every save to finish.
Anti-exploit
How the game spots and handles exploiters: whether its checks run where an exploiter can't switch them off, whether the server watches the things a client controls, such as its own character's movement and touches, and whether moderation and admin powers are protected on the server.
Report buttons, vote-kicks and client anti-cheat that let one client punish another. How to keep punishment decisions on the server or with moderators.
How to secure Touched rewards in RobloxcriticalCoins, checkpoints and finish lines that pay on Touched without checking the character is there. How to add distance checks and debounces on the server.
How to secure admin commands and admin remotescriticalAdmin panels that are only hidden on the client leave their remotes open to everyone. How to check the caller on the server in every admin handler.
Why client-side anti-cheat isn't enough in RobloxwarningAn exploiter controls their own client, so checks that only run there can be switched off. How to move movement checks to the server.
Monetisation
How the game handles Robux purchases: developer products granted through ProcessReceipt, game pass checks, and whether every purchase is granted exactly once, to the right player, and only after Roblox confirms it.
Granting products from PromptProductPurchaseFinished or a client remote isn't reliable. Why every grant belongs in ProcessReceipt.
How to write a safe ProcessReceipt callbackcriticalA ProcessReceipt that grants twice, or returns PurchaseGranted before saving, loses or repeats purchases. How to record PurchaseIds and grant exactly once.
How to check game pass ownership safelywarningTrusting the client, skipping pcall or checking only on join all break game pass perks. How to check ownership on the server and update it after a purchase.
Why ProcessReceipt must be set in one placewarningProcessReceipt is a single callback, so each script that sets it replaces the last. How to handle every developer product from one script.
Backdoors
Code that lets someone outside the team run things in the game: modules loaded from the Roblox catalogue by id, code run from strings, hidden or scrambled scripts, and scripts tucked inside models, often from the Creator Store, that do more than the model needs.
require(id) loads code from outside your game that its owner can change at any time. How to find these calls and what to replace them with.
Why loadstring is a backdoor risk in RobloxcriticalRunning code from strings with loadstring lets whoever controls the string run code on your server. How to remove it and use data instead.
How to spot hidden or obfuscated code in your gamecriticalCode pushed off-screen, strings built from character codes and getfenv lookups are common signs of a backdoor. How to find them and clean them out.
How to find scripts hidden in free modelswarningScripts inside models, parts and tools, often from free models, can create remotes or copy themselves. How to find them and check models before use.
Each guide covers one problem. Fixing every one of them makes a game harder to exploit, but it doesn't make it secure on its own: review your own game logic too.