Experienced Exploiters can find vulnerabilities in your LocalScripts and ModuleScripts, this tutorial will focus on the basics of avoiding vulnerable code that can be exploited. This tutorial will not cover how exploiters exploit and find these vulnerabilities.
In a LocalScript and ModuleScripts, any global variable, Table or function can be seen, written to, read from, and called by exploiters. Avoid global variables, functions and anything else in any LocalScript or ModuleScript, use the local keyword when creating a variable or function.
-- The following code is vulnerable to exploitation. password = "SecretPassword" function printPassword() print(password) end -- Not only can an exploiter read from or write to the password global variable -- if they desired, they can also call the printPassword global function. -- Inexperienced or unaware developers might make mistakes like these, -- and it can be unforgiving if the globals do something important.
Upvalues, essentially, are just variables used by functions. However, modern exploits have functions to get the upvalues used by functions. When an exploiter views the Lua registry they can get a list of every function and table, as well as some other things, of every LocalScript and Module script in the game. They can use these to scan for upvalues, which they can exploit.
-- The following code is vulnerable to exploitation. local password = "IThoughtThisOneWasSecure" local function printPasswordSecure() print(password) end -- Because the password variable is an upvalue, even though it is local, -- and exploiter who knows what they're doing can still read from and write to it. i -- For example: If this was an upvalue that held a guns ammo value, an exploiter -- could find it and give themselves a lot of ammo.
We can make this bit of code more secure by using function parameters.
-- A more secure version local password = "ThisOneIsMoreSecure" local function printPasswordMoreSecure(pass) print(pass) end -- The password variable can be passed as an argument instead of used as -- an upvalue. This version is more secure as the password variable can't be changed .
It should also be noted that the _G table and the shared table can be read from and written to by the client, so nothing important should be stored in these tables. This is also true for the Roblox environment and nil. Modern day exploits contain functions to get the Roblox environment (renv) as well as nil instances (anything parented to nil)
Consider adding obfuscation to LocalScripts and ModuleScripts as some exploits do have decompilers that can show the code to your LocalScripts and ModuleScripts.