Hacker prevention: Filtering and LoadStringEnabled

a guide written by jobro13

One of the most frustrating situations of a Roblox game developer is when your place gets hacked. You put some serious time into creating your game and then someone stops at your place and totally wrecks it. In most cases, this is only limited to the current server online, but sometimes these hackers go even further: they wipe your players data or steal your place, putting it up as their own.

We couldn’t really do anything about it, until Roblox decided to create some security mechanisms. They saw they couldn’t fix the exploits as fast as new ones were found. Therefore they created a waterproof system which prevents any person who actually gets access to execute scripts to replicate (upload) their changes to the servers and thus spreading it to all other players in the game.

Filtering and LoadStringEnabled

Roblox engineers have now given us a reliable option to prevent these exploits, called Filtering. This filter will, well, filter any change a client makes to the server. It uses a white list: only certain changes are allowed to make, all others are not and will silently be discarded. This does lead to a huge pain when trying to shift from a non-filtered game to a filtered game. You will need to rewrite all parts of your code which involves changing things to the server which must be replicated to everyone. These are mainly changes to the world: insertion of bullets, recoloring parts, creating buildings…


So how do you do this? First you must enable filtering: Set the option Workspace.FilteringEnabled to true. There are just a few parts that are actually on the white list. Two of them are RemoteFunctions and RemoteEvents. Their behaviour is similiar: you basically connect on the server or the client to this remote instance, and then you fire it. You can use the events in a similiar way as normal events. You can therefore connect multiple functions to run once you fire the event. If you connect to events on the client, you would normally use the server to invoke these events. You can do the same for client-server connections.

This is a sample server-client connection which explains the use:

-- Server
-- Creation must also run on the server. You can also manually create it before you upload the place.
local re = Instance.new("RemoteEvent", game.Workspace)
re.Name = "Test"
re.OnServerEvent:connect(function(player, arg)
    print(player.Name .. " called with: "..tostring(arg))
re:FireAllClients("Test", 1, {}) -- To fire only one client, use :FireClient(player) with player as player instance.
repeat wait() until game.Workspace:FindFirstChild("Test")

local event = game.Workspace.Test

event.OnClientEvent:connect(function(arg1, arg2, arg3)
    print(arg1, arg2, arg3)
event:InvokeServer("Hello from a player!")

If you only want to connect to a single function you might consider using RemoteFunctions. This can only hold one function to execute (for both client and server) which makes it ideal for procedures, such as cleaning up the workspace, recoloring a brick, etc.

You do this by defining the functions OnClientInvoke and OnServerInvoke. For example:

-- server
local rf = Instance.new("RemoteFunction", game.Workspace)
rf.Name = "Test2"
function rf.OnServerInvoke(player, arg1)
    print("Function invoke from ".. player.Name .. " with: ".. tostring(arg1))
-- Client
repeat wait() until game.Workspace:FindFirstChild("Test2")
game.Workspace.Test2:InvokeServer("Hello RemoteFunction!")

RemoteFunctions can also return values. Events cannot do this!


I've only been positive about Filtering so far. There is one issue though: if a hacker figures out how your remote instances work, they can still hack the place. If you got a function for example which is game.Workspace.RecolorBrick, then a hacker can try to recolor all bricks by trying some arguments: the brick as first argument, the BrickColor as second argument?

The last prevention you should take is to disable loadstring. Loadstring is a function where you input a lua script as string. It will return a function which you can execute. Try loadstring("print(1)")() for example. If you disable this then exploiters will get a hard time executing code. You will find LoadStringEnabled in ServerScriptService: it is disabled by default. If you enable LoadString, you cannot use PointsService! Also, this can be changed at any point where you are forced to remove loadstring. In other words: don't use it, unless you have a really good reason and you enable hackers to execute their code in your place. If you don't allow Filtering, then you should also not complain about hackers to Roblox: they have given the tools to prevent this!