Dangers of having an avatar editor & how to protect one

Starting things off, let’s say you have a RemoteEvent that let’s users load a hat into their character:

local InsertService = game:GetService("InsertService") --LoadAsset
local Remote = game:GetService("ReplicatedStorage").RemoteEvent

Remote.OnServerEvent:Connect(function(Player, Id)
	local success, model = pcall(function()
		return InsertService:LoadAsset(Id)
	end)

	if success then
		model:GetChildren()[1].Parent = Player.Character
	end
end)

There is a major problem with this system, it can load things other than hats. I’ll give an example, play test the game and run this in the command bar.

game:GetService("ReplicatedStorage").RemoteEvent:FireServer(59523967)
--59523967 is the AssetId for "SwordDispenser" by Roblox

By itself, LoadAsset will load any asset made by the Roblox account and any asset the game creator has in their inventory (even if it’s not on sale!)

The solution is a magical function in MarketplaceService, GetProductInfo!

GetProductInfo returns a lot of information, but what we’re looking for is AssetTypeId.

local Remote = game:GetService("ReplicatedStorage").RemoteEvent

Remote.OnServerEvent:Connect(function(Player, Id)
	local AssetTypeId = MarketplaceService:GetProductInfo(Id).AssetTypeId
	if AssetTypeId ~= 8 then --8 is AssetTypeId for Hat
		return
	end

	local success, model = pcall(function()
		return InsertService:LoadAsset(Id)
	end)
	if success then
		model:GetChildren[1].Parent = Player.Character
	end
end)

This is the code we have now. Play test again and try to load something other than a hat. You will no longer be able to. But wait! there’s something else we need to stop.

Certain hats have scripts in them (in general this isn’t too bad, but some hats can have some nasty code).

Take these three hats for example:
Bunny Ears of Caprice
Doombringer’s Doombringer
Teapot Turret

These hats are dangerous and shouldn’t be inserted into your game. The bunny ears will create an explosion with a huge BlastRadius, Doombringer will give admin commands to a certain user, and Teapot Turret has a tool in it that can let you kill other players.

In order to get rid of those vulnerabilities and still allow people to wear those hats, we should remove LuaSourceContainers and BackpackItems from the hat.

Our final code looks like this:

local InsertService = game:GetService("InsertService") --LoadAsset
local MarketplaceService = game:GetService("MarketplaceService") --GetProductInfo
local Remote = game:GetService("ReplicatedStorage").RemoteEvent

Remote.OnServerEvent:Connect(function(Player, Id)
	local AssetTypeId = MarketplaceService:GetProductInfo(Id).AssetTypeId
	if AssetTypeId ~= 8 then --8 is AssetTypeId for Hat
		return
	end

	local success, model = pcall(function()
		return InsertService:LoadAsset(Id)
	end)

	if success then
		for i,v in pairs(model:GetDescendants()) do
			if v:IsA("LuaSourceContainer") or v:IsA("BackpackItem") then
				v:Destroy()
			end
		end
		
		model:GetChildren()[1].Parent = Player.Character
	end
end)

This is my first tutorial thread so feedback is appreciated! :smiley:

25 Likes

Make sure to include limitations (e.g. ‘no more than 10 accessories per character’) otherwise a client could spam the server with accessories:

local remote = game:GetService("ReplicatedStorage").RemoteEvent
while true do
	remote:FireServer(4033653673)
	wait()
end

> Output: lots of lag!

Apart from that, a useful caution for inserting accessories :+1:

6 Likes