This assumes that you use FilteringEnabled. If you don't, security doesn't matter to you so you can ignore this.

It's a common misconception that FilteringEnabled stops hackers. It doesn't. That's not its job. FilteringEnabled stops hackers from having their hacks replicate to other clients. FilteringEnabled does not stop hackers from injecting Lua code. This is why it is important that your RemoteEvents are secure.

"But Kampf, I have a password/code/something so that hackers can't use my RemoteEvents!"
Yes they can. Hackers can do whatever they want. They can get your password or code. You are committing the "security through obscurity" fallacy.

"But Kampf, I renamed all my RemoteEvents so hackers can't figure out what they are!"
Congratulations, you only hurt yourself. Hackers can see what calls a RemoteEvent and see what inputs you send with it. You just make developing harder. You are also committing the "security through obscurity" fallacy.

"Kampf, what's security through obscurity? Why is it bad?"
Imagine it like this. Imagine you buried your money under a tree. The only thing that makes it safe is that nobody knows where it is. If someone finds your money, they can easily steal it because you have nothing to stop it. Compare this to storing your money into a safe. You can put this safe on a street and nothing will happen, because your money is secure, not hidden. Also, if someone finds your money (hacks your RemoteEvents), it's much harder to move all the money (fix your RemoteEvents) than to simply change a code on a safe.

"Okay, so what do I do?"
Simple. Actually secure your RemoteEvents.

There are three golden rules about networking.

  1. Never trust the client.
  2. Never give the client too much power.
  3. Everything that can securely be handled on the client should be handled on the client.

The big ones are the first and second rules.

By "never trust the client", I mean never trust the client.

Let's say I had a Server Script that lets players deposit money into their bank accounts.

game:GetService("ReplicatedStorage").DepositMoney.OnServerEvent:Connect(function(ply, num)
    ply.Moneyz.Value = ply.Moneyz.Value - num
    ply.Bank.Value = ply.Bank.Value + num
end)

Do you see the problem? We don't check if the number is at all valid. Do we check if it's a number? No. Do we check if it's negative? No. Do we check if they have enough in their account? No.

A hacker can run this line of code:

game:GetService("ReplicatedStorage").DepositMoney:FireServer(-999999)

And they'd be RICH!

What's the solution? Easy.

game:GetService("ReplicatedStorage").DepositMoney.OnServerEvent:Connect(function(ply, num)
    if typeof(num) ~= "number" then return end --Is num a number? If not, stop the script. I kick the player here.
    if num < 0 then return end --Is num negative? If not, stop. Again, I'd kick the player here.
    
    if ply.Moneyz.Value >= num then --Do they have enough moneyz?
        ply.Moneyz.Value = ply.Moneyz.Value - num
        ply.Bank.Value = ply.Bank.Value + num
    end
end)

Get the point? Never trust the client. Make absolutely sure their inputs are valid before doing what you want.

Now let's talk about "Never give the player too much power".

Let's say we had a gun, but because we want to avoid latency, we handle all the firing on the client.

--DO NOT USE THIS

tool.Activated:Connect(function()
    for _,victim in pairs(getEnemiesInFiringRange()) do
        game:GetService("ReplicatedStorage").DamagePlayer:FireServer(victim)
    end
end)

I'm sure (and if you can't, I'm scared) you can understand the problem here. A hacker can just run this.

while wait(1) do
    for _,player in pairs(game:GetService("Players"):GetPlayers()) do
        game:GetService("ReplicatedStorage").DamagePlayer:FireServer(player)
    end
end

Oh my. What's the solution? Suck it up and take the latency. Players might complain about lag in your game, but tell them it's better than having hackers being able to kill everyone.

This also goes into our third rule. How do we know what the client should do and what the server should do?

I'll give a couple examples.

You should be asking the following questions: Can the server do it? Can the client do it? If the client does it, does it open up a security vulnerability?

Guns:

  • Can the server do it? - Yes
  • Can the client do it? - Yes
  • If the client does it, does it open up a security vulnerability? - Yes

Because the answer to the third question is yes, we should handle guns on the server.

Round Timer Countdown:

  • Can the server do it? - Yes
  • Can the client do it? - Yes
  • If the client does it, does it open up a security vulnerability? - No

Because the client is fully capable of showing a timer for a round without breaking security, let the client do it. This results in less latency and less stress for the server.

I hope this helps you with securing your game. Remember the three golden rules when developing RemoteEvents, and hopefully you'll be fine.