I understand that sending instances through RemoteEvents is generally discouraged due to potential safety concerns or errors. Still, I’ve found myself in a situation where I’m unsure if it’s the most efficient solution or not.
I’m building a custom item pickup system that doesn’t use proximity prompts, click detectors, or character touch detection. This is intentional for how my system is designed. A client sided script has its own way of detecting which item the player is targeting and intends to pick up. This means the choice of which item to pick up is handled entirely on the client.
Here’s the goal:
A local script detects which item (a model in Workspace) the player is trying to pick up. It then tells the server which item it is, so the server can delete said item, and attribute it to the player (aka, make the player “collect” the item).
My direct and simple idea for a solution:
(In this context, the term “Instance” refers to the model that the player aims to pick up, located in the workspace, representing an item.)
My idea is to have the client detect the model and send it directly to the server via a RemoteEvent, basically saying:
“[This player] wants to pick up [this instance].”
-
If the instance doesn’t exist, the server ignores it.
-
If the client modified it, no issue. The server would use the original, server-side instance, since any changes made to it on the client would not be replicated.
-
The server then deletes the model and assigns the corresponding item to the player.
The dilemma I’m facing:
Scripting-wise, this works fine and should be easy to achieve. My concern is purely theoretical. Is this approach safe enough?
Here is an alternative I’ve considered:
If sending the instance directly is unsafe, I could build a server-side “registry”. This would be a table of all item models and their unique IDs. The client would then, grab the ID of the model/item the player is targeting, and send its ID only to the server. The server would then reference the registry to find and detect the correct model.
Basically:
“[This player] wants to pick up item with [this ID]”
- The server checks the list of instances, and uses the ID received from the client to find which specific model that player chose.
This second registry idea seems more reliable and study, but it adds a lot of complexity. From what I’ve seen online (and I’ve seen a lot), people have very mixed feelings on the topic of sending instances via remotes. Some say it’s safe if you take the precautions, some say it’s something you should absolutely never, ever do! That said, in my case, is it worth the extra effort to make a registry for all “grabbable” items currently in workspace, and use IDs so the client can specify to the server which item it wants, or can I safely just have the client send the instance if I do proper server-side validation?
Some extra things to be taken into consideration:
What am I aware of?
-
That with proper server-side validation, this approach should, in theory, be safe, but I’m not entirely confident, which is why I’m seeking advice.
-
That client-made instances won’t replicate to the server, and the server will receive nil from the remote. That said, the client can’t fake items.
Extra potential risks I’m aware of:
- Exploiters might attempt to pick any item instantly. This can be mitigated by checking distance between the player and the target item on the server.
Edit: It is also important to clarify this isn’t an “item giver”, but a proper item collection system. Multiple identical or different items may be scattered across the workspace, so it’s imperative that the server identifies the exact model the client is targeting.
TL;DR:
I want the client to send an item instance to the server when picking it up. It works, but I’m unsure if it’s safe even with validation. The safer alternative is attributing item IDs to each item and sending that instead, but it’s more work. I’m on the fence between simplicity and security, and unaware of potential downsides for either approaches.
Edit + Solution:
The second solution, assigning unique IDs for each item, and building a “registry” that references the models using said IDs, is in fact more efficient and secure.
As pointed out by user “d05dev”, sending the instance from the client to the server through a remote can result in reference leaks, instance spoofing, denial of service, race conditions, and other issues, and should therefore not be done.