How to safely invoke the client

its me again

Alright, so did you know if you ever invoke the client using remotefunctions, your opening up opportunities of exploiters to damage your server? its interesting. not really but ill show you how to prevent this

lets say you have the client, like this
image
(ignore the remote name lol)

yes, the server will print “Hello, server!”

and the exploiter changes it to this:
image
this would damage the server, but with this method of safely invoking the client, you will instead get
image
Oh and it also works if the exploiter infinitely yields the server too. Want to implement this? Ok follow my steps.

  1. create some variables dude!
game.Players.PlayerAdded:Connect(function(plr)
task.wait(2)
--safe invoke
local timeoutcount = 0
local timeout = 5
local result = nil
end)

give the client some time to return a value! (Edit timeout value, just dont mess with timeoutcount)
and result will be important, leave it nil, you will know why its important later

  1. Lets multithread
local urremoteevent = replicatedstorage.urremoteevent
game.Players.PlayerAdded:Connect(function(plr)
task.wait(2)
--safe invoke
local timeoutcount = 0
local timeout = 5
local result = nil
task.spawn(function()
local som = urremoteevent
               
end)
end)

this is important, because were gonna check if it can be used or is bad

  1. Check the type bro! it could be bad or not needed
local urremoteevent = replicatedstorage.urremoteevent
game.Players.PlayerAdded:Connect(function(plr)
task.wait(2)
--safe invoke
local timeoutcount = 0
local timeout = 5
local result = nil
task.spawn(function()
local som = urremoteevent:InvokeClient(plr)
if typeof(som) == "string" then -- ofcourse, change string with whatever u like
result = som
end
end)

end)

basically checks the type of the result the client gave you, if its not the one you need it will drop it

  1. Waiting for timeout, we can’t wait all day
local urremoteevent = replicatedstorage.urremoteevent
game.Players.PlayerAdded:Connect(function(plr)
task.wait(2)
--safe invoke
local timeoutcount = 0
local timeout = 5
local result = nil
task.spawn(function()
local som = urremoteevent:InvokeClient(plr)
if typeof(som) == "string" then -- ofcourse, change string with whatever u like
result = som
end
end)
repeat task.wait(1) timeoutcount += 1 until timeoutcount >= timeout or result ~= nil
end)

This repeat event will yield until timeout count is the same or bigger than the timeout u gave, or until result is not nil(~= nil)

  1. Finally, do whatever you want with this result.
local urremoteevent = replicatedstorage.urremoteevent
game.Players.PlayerAdded:Connect(function(plr)
task.wait(2)
--safe invoke
local timeoutcount = 0
local timeout = 5
local result = nil
task.spawn(function()
local som = urremoteevent:InvokeClient(plr)
if typeof(som) == "string" then -- ofcourse, change string with whatever u like
result = som
end
end)
repeat task.wait(1) timeoutcount += 1 until timeoutcount >= timeout or result ~= nil
if result ~= nil then
print(result) -- replace this with whatever u want to do with result
else
plr:Kick("Unexpected behaviour : timeout reached")
end
end)

Were done! now the clever or not exploiters cant mess with ur remotefunction anymore! epic!

Credits to @CodedJer , he made a formatted version to clearly read it.

local players = game:GetService("Players")
local replicatedStorage = game:GetService("ReplicatedStorage")

local urremoteevent = replicatedStorage.urremoteevent
players.PlayerAdded:Connect(function(plr)
	task.wait(2)
	local timeoutcount = 0
	local timeout = 5
	local result = nil
	task.spawn(function()
		local som = urremoteevent:InvokeClient(plr)
		if typeof(som) == "string" then
			result = som
		end
	end)
	repeat
		task.wait(1)
		timeoutcount = timeoutcount + 1
	until timeoutcount >= timeout or result ~= nil
	if result ~= nil then
		print(result)
	else
		plr:Kick("Unexpected behaviour : timeout reached")
	end
end)

Feedback is appreciated

17 Likes

Please format your code if you want people to actually follow what you’re doing.

9 Likes

Ill format it a bit later. But I still don’t see what’s wrong with the formatting

Code indention and spacing is just easier for people to read as opposed to having everything to the left

3 Likes

Alright I will do it a lil later, I’m busy rn

If you want to safely invoke the client, you need to wait for the client to tell you they loaded. Oftentimes the client will load for more than two seconds.

You can use ‘game:IsLoaded()’ and ‘game.Loaded:Wait()’ for this.

if not game:IsLoaded() then
   game.Loaded:Wait()
end
-- fire your ‘GameLoaded’ remote here
3 Likes

They can infinitely yield the server like this xdd

thus there is a timeout so

game.Loaded:Wait() might infinitely yield since it only fires one, if you don’t want it to infinitely you can use repeat RunService.Heartbeat:Wait() until game:IsLoaded()

What I meant that if I make a remotefunction and wait for the client to tell me that their loaded, they can easily make an infinite yield

Sorry for the misunderstanding lol

1 Like

What Is this supposed to do, I do not understand due to the formatting.

when you use remotefunctions to invoke the client, the exploiter can infinitely yield server, so this serverscript is basically a timeout thing.

what is that ? Is the handshake system like the timeout thing?

No pcalls? The documentation for InvokeClient specifically mentions wrapping in a pcall to prevent errors

I think task spawn already handled this for you

It won’t stop the current thread from continuing but it doesnt exactly catch the error either
(Nor is invoking the client ever truly safe)

Then add a pcall I guess.

This post is inherently misleading, due to the fact that exploiters can still hook onto your OnClientEvent‘s using metamethods. There is no “safe” on the client, no matter how hard you try. You might slow down script kiddies and exploiters who have no knowledge on this, but any competent exploiter can still, very well, just spoof the data.

2 Likes

I would like to see you make a code that yields the server infinitely.

What? No one is able to do that without a server sided vulnerability?

I think you’re misunderstanding me. Im saying method you have provided doesn’t seem very practical or safe as a security measure as you claim it to be.