Is ChildRemoved able to trigger a Script on client side by hackers

If I were to put a script that uses ChildRemoved in a part. Would a hacker
be able to remove a child of said part from client side and trigger the ChildRemoved from the server script?

No, unless the player has explicitly been given network ownership over the part. It should be safe to use it in most cases

2 Likes

Changes on the client do not appear on the server. Maybe try hiding a local script somewhere and use that.

Short answer: no (except in a special case scenario).

Long answer:

Anchored parts

~ are not physically simulated themselves. They are static, are only part of the physics update so long as they can affect other parts with touch and so on.

Unanchored parts

~ are subject to physics simulation. Network ownership comes in play, as @Bloxlin_Dev already mentioned. Server unburdens itself from lots of calcuations by allocating some of the work and leave control of the part to the nearest client.

Can clients delete any parts outside their character? No.

Can clients delete any parts of their character or placed inside their character? Not anymore. Since May 1st this year, workspace.RejectCharacterDeletions is enabled by default. Unless manually disabled, players can no longer delete parts in/of their character either.

Exception

Player throws the part into the void.

I’ve written a quick example script. Tossing the part into the void will remove the part, unless the it’s strongly referenced by the server.

Version 1
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

local observedFolder = Instance.new("Folder")
local garbageFolder = Instance.new("Folder")
observedFolder.Parent = workspace; garbageFolder.Parent = workspace

Players.PlayerAdded:Connect(function(player)
	player.CharacterAppearanceLoaded:Connect(function(character)
		do local observed = Instance.new("Part"); task.wait()
			observed.CFrame = character.HumanoidRootPart.CFrame * CFrame.new(0,0,-10)
			observed.Parent = observedFolder
		end
		
		observedFolder.ChildRemoved:Connect(function(child)
			print("Removed")
		end)
	end)
end)
Version 2
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

local observedFolder = Instance.new("Folder")
local garbageFolder = Instance.new("Folder")
observedFolder.Parent = workspace; garbageFolder.Parent = workspace

Players.PlayerAdded:Connect(function(player)
	player.CharacterAppearanceLoaded:Connect(function(character)
		local observed = Instance.new("Part"); task.wait(2)
		observed = observed -- weak copy
		observed.CFrame = character.HumanoidRootPart.CFrame * CFrame.new(0,0,-10)
		observed.Parent = observedFolder
		
		local weakReference = setmetatable({}, {__mode = "v"})
		
		observedFolder.ChildRemoved:Connect(function(child)
			print("Removed") --> Removed
		end)
		
		weakReference["Observed"]:GetPropertyChangedSignal("Parent"):Once(function()
			print(weakReference["Part"]) --> nil
		end)
		
		observed = nil -- lose strong reference
		
		-- Stimulate garbage collection.
		RunService.Heartbeat:Connect(function(dt)
			local part = Instance.new("Part")
			part.Parent = garbageFolder
			task.wait(1); part:Destroy()
		end)
	end)
end)
1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.