It’s not effectively useless. It just means that I need to be wary of exploiters deleting objects when writing my scripts.
Though this does mean that anticheat scripts should not go into a player’s character. They must handle the character externally.
I propose a solution to this issue.
Most instances being deleted under the character are extremely dangerous (especially the Humanoid itself since this allows for invincibility). Tools, clothing, etc can be deleted. If a tool required for progression is deleted by the client, how will progression occur? A player can delete their clothing and they won’t have default clothing. However, I am sure in some cases the client itself actually needs to use this behaviour (e.g. with the Animator object).
Knowing this behavior is most likely required, why not simply whitelist instance classes? For example,
BasePart, and joint instances (e.g.
JointInstance and constraints).
This allows for required client behavior to function as intended, but the client cannot delete important items such as
Configuration, and other instances.
The client has a weird psuedo-control over its humanoid. I don’t believe this is a bug, it just is what it is. And what it is, is something that spites the entire point of FE as 90% of exploits that exploiters use globally work off of this precedent. I’ve seen some really crafty stuff from this vulnerability over the years as well.
- Players being able to trick the server into believing their Character is somewhere else than where it is on the client (this results in a sort of invisibility in which players are able to abuse tools such as the linked sword to kill other players without ever being seen)
- Players being able to spoof touch events and interact with things that they really shouldn’t be able to interact with
- Players being able to accomplish god mode, essentially making themselves invincible
- Players being able to abuse tools to fling other players
- Players being able to abuse their own character joints to fling other players
- And of course you also have your standard fly hacks, noclip, speed hacks, etc…
This is precisely why I recommend creating your own custom character system in which the player’s character is handled entirely by the server, and the client only sends basic requests to interact with the server. It may not exactly be ideal for mobile, but it’s worth looking into if these vulnerabilities break your game.
Can we please get an update or acknowledgement of this issue? This behaviour is not documented.
I now have to store character health (instead of relying on the humanoid existing) and a number of BindableEvents in a separate location. This is a lot more inconvenient than just having access to them in the character. It also has wider security implications because there is zero guarantee anything related to the character actually still exists, even if it existed once the character is spawned (in which I continually assume it still exists while the character is alive).
Why not just oof the character when a critical component disappears?
DescendantRemoving is your best friend in this case.
Also this ruins client-sided effects for FilteringEnabled. Even if I only want my client to see changes made to the character, I now need to worry about handling the changes replicating to the server.
It’s a huge web I need to work through now that I’m aware of this behavior. This should 100% be changed instead of forcing me to make my own hacky replication for stuff I expected to function properly out of the box.
The reason I said it becomes useless is because there are otherwise better places to put your (server-side) scripts so that exploiters can’t just delete them. Why be wary when you could just put it somewhere else?
I actually created a vanilla Humanoid system in which the character is controlled by both the server and client, however the client only has limited control. I’ll have to unarchive it when I get a chance. I may uncopylock the place as well, we’ll see. Currently it’s a little unstable but it fixes a majority of movement exploits. Additionally, due to it being custom replication this fixes touch issues as well.
As for deleting descendants of the character, it is possible to detect this (e.g. such as how I’ve done above), however it’s a similar situation where it’s hard to filter between client vs server changes so you’d have to implement custom destruction of instances as well.
I really really REALLY think most of this behaviour needs to change though. It defeats the purpose of filtering enabled and causes a TON of issues in 95% of games not to mention the fact that it’s completely undocumented.
Except property changes made to the local character don’t replicate; only the destruction of objects do; so there is no “control over the entire character instance.” It’s either a bug or a very stupid feature.
I personally cannot see any reason why the client should be authorized to delete instances of the local character (considering, especially, that property changes do not replicate).
Only physics-related data (position, velocity etc) and calculations handled by the client (should) replicate. This is true for all other BaseParts which the client has network ownership of (deleting those doesn’t replicate).
I think I am going to make a custom character controller to alleviate this (it’s apparently been 6 years without a solution). It’s a little sad that it renders StarterCharacter/etc effectively useless in that case, because otherwise I would use them.
Exploiters can’t work around a server sided instance removal check. If they remove something from their character and it replicates, then the server will see it removed.
Does this still happen? Does this mean I can’t trust humanoid.health and the default health script to be accurate?
Humanoid.Health is a property, and as such isn’t affected by this. The only thing that is replicated is when the client deletes an instance under their character. As for the default health script, the client can delete that however all they’d be doing is stopping their own health regeneration, as the health script is only for managing the player’s health regeneration over time. Overall, this means the player can’t do much by default unless they want to stop their own health regeneration, if you’re worried about exploiters doing game-breaking things I’d check for what you parent under the character like scripts or instance tags. (E.g: using a folder parented to the player’s character for managing whether the player is stunned. You can fix this by using CollectionService and using AddTag as that won’t replicate from the client.)
Ok so I’d also need the server to check if a player destroys an instance they’re not supposed to under their character
I hope this is addressed properly. Developing a game on this platform feels like I’m diving through a dumpster of broken and undocumented ‘features’. We are taught again and again to “never trust the client”, but so many Roblox features ignore that lesson so now we’re stuck having to patch it ourselves. Now not only do I have to worry about making sure my own code is secured, I have to dig around on the forums to find all of the weird miscellaneous exploits with the engine and write hacky alternatives to them as well.
11 months later and this bug has still been around. It would be nice if we could get any sort of acknowledgement from the staff about this.
This makes the existence of StarterCharacterScripts pointless and that really sucks because I relied on the folder a lot during the development of my game. Now I’ll have to reorganize everything…
Is this not intended? I’d think the client needs network ownership of the Character model to function properly.
It’s understandable for the client to have network ownership of their own character; however, it gets frustrating once you realize the client is also able to replicate destruction of Instances within their character model, which leads to people dropping hats, removing meshes from parts, deleting clothes, and making floating accessories.
AFAIK networkownership doesn’t require them to be able to delete instances and it replicating.
Bumping this because this issue is the bane of my existence. I am trying to manually replicate content between clients and servers, but this makes it impossible, as I can’t just delete the server sided objects on the client otherwise they will be gone for everyone else too. No idea how else I am supposed to be replicating things such as character look or the facial expressions of the characters without having a local and server sided copy, and without using animations.