How can you make a script stay the same from being changed?

I tried my best to make this script work. Somehow, it’s easily bypassed. Take a look at this code and see what you can improve or change

script.Changed:Connect(function(ch)
	xpcall(function()
		if script.Parent == nil then
			script.Parent = game:GetService("ServerScriptService")
		end
		
		if ch == true then
			ch = not ch
		end
end)
end)

Just to let you know, it made my studio freeze from doing this.

2 Likes

Do you think you can explain what the intent of this script is for?

Also for non ValueBase instances (StringValue, BoolValue, ect.), the argument passed to your listener when called is the name of the property that changed. So ch could be "Disabled", or "Name", for example.

The intention of this script is to avoid any changes being made to the script.

Ok, and can you explain how it is bypassed? And why would you want it to not change? As well as specify the script type and location?

Just so you know, whenever an instance’s Destroy method is called, it doesn’t only set its parent to nil, but also locks it so that it can’t be set back.
I guess the simplest way to bypass it is to make the script clone itself and set the clone’s parent to SSS, but since scripts can’t run in nil, I doubt it would work.
Otherwise, scripts only have four writable properties other than the parent, .Name, .Archivable, .LinkedSource, and .Disabled. You can just cache them in the code and set them on the .Changed event.
You would probably have to make a different script detect when yours in question changes, which is what I typed here:

local Target = game:GetService("ServerScriptService").Script

local Cache = {
	Parent = Target.Parent,
	Archivable = Target.Archivable,
	LinkedSource = Target.LinkedSource
	Name = Target.Name
}

local onChanged; function onChanged(prop)
	-- print(prop,Target[prop])
	if prop == "Parent" then
		local new = Target:Clone()
		new.Parent = Cache.Parent
		Target = new
		new.Changed:Connect(onChanged)
	else
		Target[prop] = Cache[prop]
	end
end

Target.Changed:Connect(onChanged)

You could probably then make Target have the same code as above and configure it to connect to the original one, and the scripts would watch each other’s backs.
I just tried deleting both scripts at the same time from the explorer, and that surprisingly did not work, so I guess this would be your solution.

What’s even the purpose of doing this? The only thing that can change server-sided scripts are other server-sided scripts and unless you have some kind of odd coding practices going on here, there should be no reason for you to detect and undo changes.

2 Likes

Let me rephrase my statement a bit. I just wanted to know how to do this since I didn’t want exploiters to like clear out all children from ServerScriptService. I also didnt want it being disabled just so that my own admin commands wont break from being used. However, Im still practicing how to detect exploiters and also lock scripts from being deleted. Practically, Im hoping to make a game that can be protected from being changed. I understand how much explaining I have to do, just that Im just knowing how to make instances non-changeable. But thanks for asking though.

Exploiters can’t access ServerScriptService. Detecting exploiters is less useful than securing your game and understanding proper practices to defend against them. Locking scripts from being deleted is extremely pointless and in some cases does not even work, such as if Destroy is called.

You shouldn’t be doing this at all.

3 Likes

Hm. Alright, I might find another way, too.

1 Like

I saved this as a draft, so I’ll just post it here anyway:

Just so you know, exploiters will never be able to find, modify, or destroy instances found in ServerScriptService and ServerStorage, period.
The only way they would have access is through vulnerable remote events/functions or server backdoors, which should be easy enough to avoid as long as you know how to trust your clients and plugins respectively.

Some Tips
  • Clients should request actions and data, and the server should check its validity before responding, not just let the clients do the actions. You should never trust what the client says, because they might be an exploiter.

  • Good plugins you find will usually come from a trustworthy member of the Roblox community. Check the creator’s profile for anything sketchy before considering downloading their plugin.

1 Like