I cannot think of a reason why ROBLOX has not implemented something like this. To me, it adds the option to enhance security immensely. This is more of a why not kind of question.
To be more specific: for remotes, why doesn't ROBLOX check for some callback function to execute before sending data over the network?
It seems to me that you could easily filter out when a remote is supposed to be fired, and when it is not, if they just granted us the option to run some code before the remote actually sends anything. For example, say the FireServer
method behaved something like this internally:
function Remote:FireServer(...) local validInvocation if self.OnRemoteFired then validInvocation = self.OnRemoteFired(...) if not validInvocation then return -- discontinue end end -- valid invocation; function may proceed to update the server sendDataToServer(...) end
This way, we could just wrap FireServer
inside a new function which uses some debounce
gate that allows FireServer
to actually send data if the gate lets it through. If the callback returns false
or nil
, then the call to FireServer
is negated. Otherwise, proceed normally. Here's a practical example of what I'm talking about if such a callback existed:
-- debounce state in which data can be sent over the network -- true: data can be sent -- false: data cannot be sent local networkSendState = false -- set callback function -- if networkSendState is true, the callback will return true, which in turn will allow FireServer to proceed normally. function Remote.OnRemoteFired(...) return networkSendState end -- wrapped version of FireServer created by the developer local function NewFireServer(remote, ...) networkSendState = true -- open gate remote:FireServer(...) -- send data over network networkSendState = false -- close gate end
Now the client can tell if the call to FireServer
was legitimate or not depending on the networkSendState
. You, as the developer, now only use NewFireServer
so that you have complete control over the gate, allowing you to pass through.
Suppose a developer now wants to catch an exploiter firing a remote
function Remote.OnRemoteFired(...) if not networkSendState then print("Invalid FireServer invocation! Possible exploiter!") return else print("Valid invocation to FireServer") end return true end NewFireServer( ... ) -- opens gate to send "..."
Valid invocation to FireServer
Remote:FireServer( ... ) -- gate was not opened, will not send "..."
Invalid FireServer invocation! Possible exploiter!
Easy, right?
I need someone who's smarter than me on this one. Would this actually add a significant layer of security to network communication among ROBLOX games, or am I completely missing something and it creates more problems than solutions? Any input on this would be fantastic, as I've pondered this simple thought for a while.
Edit in Response to: Kiriot22
You brought up a valid point about overwriting OnRemoteFired
, but couldn't that easily be fixed as well?
local Remote = {} local Remote_mt = {} function Remote_mt:__newindex(k, v) if self[k] and k == "OnRemoteFired" then return end end setmetatable(Remote, Remote_mt)
Response to your edit.
You cannot just assume they don't have access to the debug
library.
Now, in your previous code samples I thought the Remote
variable is a RemoteEvent
instance and not a table? And now you're saying it's a table.
But even if it was a table, you can still bypass __newindex
by using rawset()
or even debug.getmetatable()
.
Here's a code that an exploiter could use to bypass your check, if remote callbacks were a thing:
for i,v in pairs(debug.getregistry()) do if type(v) == "function" and debug.getupvalues(v).Remote then rawset(debug.getupvalues(v).Remote, "OnRemoteFired", newcclosure(function() return true end)) break end end