Are these RemoteEvents secure?

I apologize if this seems like a weird question - but I haven’t done scripting relative to RemoteEvents in awhile as I focused my attention more towards redesigning my UI’s & architectural work in general. Just want to make sure everything is secure before implementing it into my new game, thanks!

local

local GamePassService = game:GetService('MarketplaceService')
local player = game.Players.LocalPlayer 

script.Parent.MouseButton1Down:connect(function()
	
	if player:IsInGroup(5770388) or GamePassService:UserOwnsGamePassAsync(player.userId, 4702761) then
		
		local group = 5770388
		local gp = 4702761
		
		game.ReplicatedStorage.GUI.Assign:FireServer(BrickColor.new("Mint"), group, gp)
		
		
	else
		
		local gp = 4702761
		
		game:GetService("MarketplaceService"):PromptGamePassPurchase(player,gp)
		
	end
	
end)

server

local GamePassService = game:GetService('MarketplaceService')


game.ReplicatedStorage.team.OnServerEvent:connect(function(plr, color, group, gp)
	if plr:IsInGroup(group) or GamePassService:UserOwnsGamePassAsync(plr.userId, gp) then
	plr.TeamColor = color
	plr:LoadCharacter()
	end
end)

Exploiters can edit local scripts meaning they can fire your remote event and change the arguments - Instead you should perform group and gamepass checks all inside the server script.

Say I was an exploiter:
I would fire your event and change the group id to a group I’m a part of or change the gamepass id to a gamepass I own.

1 Like

An exploiter could just just pass a group that they are in or any random Gamepass that they have in their inventory. It should not be possible for the client to be able to pick which group or Gamepass it wants to be checked.

-- client
local GamePassService = game:GetService('MarketplaceService')
local player = game.Players.LocalPlayer 
local gamepassid = 4702761
local groupid = 5770388

script.Parent.MouseButton1Down:connect(function()
	if player:IsInGroup(groupid) or GamePassService:UserOwnsGamePassAsync(player.userId, gamepassid) then
		game.ReplicatedStorage.GUI.Assign:FireServer(BrickColor.new("Mint"))
	else
		game:GetService("MarketplaceService"):PromptGamePassPurchase(player, gamepassid)
	end
end)
-- server
local GamePassService = game:GetService('MarketplaceService')
local gamepassid = 4702761
local groupid = 5770388

game.ReplicatedStorage.team.OnServerEvent:connect(function(plr, color)
	if plr:IsInGroup(groupid) or GamePassService:UserOwnsGamePassAsync(plr.userId, gamepassid) then
		plr.TeamColor = color
		plr:LoadCharacter()
	end
end)
1 Like

Right so for example - should I have the remote event fire off the name of the team; and then the server will check if they own gp or are in the required group for the team. Which if so, change their team.

I updated my reply with the code that should work, your client should do proprietary & group checks for efficiency and the server should be a last resort in case an exploiter fired your remote without those checks.

1 Like

So using

-- client
local GamePassService = game:GetService('MarketplaceService')
local player = game.Players.LocalPlayer 
local gamepassid = 4702761
local groupid = 5770388

script.Parent.MouseButton1Down:connect(function()
	if player:IsInGroup(groupid) or GamePassService:UserOwnsGamePassAsync(player.userId, gamepassid) then
		game.ReplicatedStorage.GUI.Assign:FireServer(BrickColor.new("Mint"))
	else
		game:GetService("MarketplaceService"):PromptGamePassPurchase(player, gamepassid)
	end
end)

— server
if color == BrickColor.new(“Sand red”) and plr:IsInGroup(ACTUALID) or GamePassService:UserOwnsGamePassAsync(plr.userId, ACTUALID) then

plr.TeamColor == BrickColor.new("Sand red")

else 

  if color == BrickColor.new("Really blue") and  plr:IsInGroup(ACTUALID) or GamePassService:UserOwnsGamePassAsync(plr.userId, ACTUALID) then

    plr.TeamColor == BrickColor.new("Really blue")

    end

[which then repeat the else until i’ve covered all teams]

Why is this necessary? If you have different gamepasses for different colors then I understand, but in your pseudocode example you seem to be using the same IDs which is confusing me. If you only need to own one gamepass to have an ultimate range of BrickColors, then don’t bother checking the color at all (maybe only check if it’s an actual BrickColor, although for security purposes, passing an invalid color wouldn’t affect much).

I said (ACTUALID) – they would be different ID’s for each color.

Which is why I am implying using the “else” statement to continue the checks for the rest of the teams once they are fired off from the client.

I’ve been developing for about 4 hours now and got a bit lazy, didn’t feel like putting actual numbers into place. Sorry for the confusion.

Essentially - the code is checking which color is being fired, and then checking if they are in the designated group or own the gamepass for that color before changing their team.

---- Further reference:

Use a lookup table with BrickColors and ID’s then.

local colors_gamepasses = {
	[BrickColor.new("Sand red")] = 12345,
	[BrickColor.new("Really blue")] = 6789
}
local groupid = 5770388
local GamePassService = game:GetService('MarketplaceService')

game.ReplicatedStorage.team.OnServerEvent:connect(function(plr, color)
	local gamepass = colors_gamepasses[color]
	if gamepass then
		if plr:IsInGroup(groupid) or GamePassService:UserOwnsGamePassAsync(plr.UserId, gamepass) then
			plr.TeamColor = color
		end
	end
end)

Right - keep in mind different group ID’s as well, would I just add

local colors_ids = {

    [BrickColor.new("Sand red")] = 8963113,
	[BrickColor.new("Really blue")] = 872987
}

to it along with

local groupid = colors_ids[color]

Sure, you could also keep it all in one and format it like this:

local lookup = {
	[BrickColor.new("Sand red")] = {group = 1234, gamepass = 6579};
	...
}
local GamePassService = game:GetService('MarketplaceService')

game.ReplicatedStorage.team.OnServerEvent:connect(function(plr, color)
	local info = lookup[color]
	if info then
		if plr:IsInGroup(info.group) or GamePassService:UserOwnsGamePassAsync(plr.UserId, info.gamepass) then
			plr.TeamColor = color
		end
	end
end)
1 Like

I like that - a lot more organized, appreciate the help a lot.

1 Like