How to find scripts hidden in free models

Scripts inside models, parts and tools, often from free models, can create remotes or copy themselves. How to find them and check models before use.

warningLuaudit check: stray-scripts

What it looks like

A Script sits inside a model, part, tool or service where you wouldn't expect code, usually because it came with a free model. It may do nothing obvious, copy itself into other objects, or create remotes and modules at run time.

Luau
for _, model in workspace:GetDescendants() do
	if model:IsA("Model") then
		script:Clone().Parent = model
	end
end

How to detect it

  • List every Script and ModuleScript outside the usual places: ServerScriptService, ServerStorage, ReplicatedStorage, ReplicatedFirst, StarterPlayer, StarterGui and StarterPack. Scripts in Workspace models, parts, Lighting, SoundService, Teams or Chat need reading.
  • For each, check whether the code does only what its model needs, like a door opening or a light flickering. Treat as findings: copying script into other objects, creating RemoteEvents or RemoteFunctions, require with a number, loadstring, getfenv, HttpService requests, and changes to unrelated parts of the game.
  • Look for names that try to look official or harmless, like Vaccine, Fix, Weld, Spread, ThumbnailCamera or ROBLOX, and for more than one copy of the same script across many models.
  • In a Rojo project, models saved as .rbxm files can't be read as text. Say which ones you couldn't check.

What an exploiter could do

A self-copying script spreads through the place and every copy runs on its own, which slows servers down and can keep coming back after you delete some copies. Scripts that create remotes or load code give whoever made them a way into the server.

How to fix it

  • Delete scripts that don't belong to the model's job, along with every copy, then search for anything they created.
  • Keep game code in ServerScriptService and the client folders, so stray scripts stand out.
  • Check free models before using them: open each script inside and read it.

Vulnerable example

Vulnerable
local Workspace = game:GetService("Workspace")

local props = Workspace:WaitForChild("Props")

for _, model in props:GetChildren() do
	if model:IsA("Model") and not model:FindFirstChild(script.Name) then
		script:Clone().Parent = model
	end
end

Fixed example

Fixed
local Workspace = game:GetService("Workspace")

local lamp = Workspace:WaitForChild("Props"):WaitForChild("Lamp")
local bulb = lamp:WaitForChild("Bulb") :: BasePart
local light = bulb:WaitForChild("PointLight") :: PointLight

while true do
	task.wait(math.random(4, 9))
	light.Enabled = false
	task.wait(0.1)
	light.Enabled = true
end

Common false positives

  • A script inside a model that only drives that model, like a door, a lift or a flickering light, is normal.
  • Scripts in tools that only run the tool are expected.
  • Client scripts in StarterPlayer or StarterGui aren't stray, even if they're large.