How to stop players dropping paid tools for others
A paid tool that can be dropped can be handed to anyone, again and again. How to lock paid tools to the player who bought them.
What it looks like
A game pass or developer product gives the player a Tool, such as a VIP sword, a speed coil or a gravity coil. The tool's CanBeDropped is true, so the buyer can drop it into the world, where anyone can walk over it and take it. Often the server gives a new copy on every respawn, so one buyer can hand out as many as they like.
player.CharacterAdded:Connect(function() if ownsPass(player) then ServerStorage.GravityCoil:Clone().Parent = player.Backpack end end)
How to detect it
- Find every tool given because of a purchase: game pass checks,
ProcessReceiptgrants and paid crates. - Roblox's reference for
Tool.CanBeDroppedsays that when it'strue, pressing Backspace parents the tool toWorkspaceand removes it from the player'sBackpack. Roblox's tools guide describes tools placed in the world as pickups that players collect. - Check
CanBeDroppedon the tool in the place or project file, and anywhere a script sets it. Report paid tools that can be dropped. - Check how copies are handed out. A tool given again whenever the backpack doesn't have one, such as on each respawn, can be dropped and replaced over and over.
- Dropping a paid item for another player is also trading it. If the game checks
PolicyServiceIsPaidItemTradingAllowedfor trades and gifts, dropping goes around that check. See Paid items traded with no policy check.
What an exploiter could do
They buy the pass once, or get one from a friend who did, then drop the tool, respawn, and drop it again until everyone in the server has one. Players get paid perks for free, sales fall, and paid weapons end up in the hands of players the game never meant to have them.
How to fix it
- Set
CanBeDroppedtofalseon every paid tool, in the saved tool and again when cloning it. - Check on the server that a player using a paid tool owns it, for example in the tool's server script, so a copy that does change hands doesn't work.
- If dropping is part of the game, only let free tools be dropped.
Vulnerable example
local MarketplaceService = game:GetService("MarketplaceService") local Players = game:GetService("Players") local ServerStorage = game:GetService("ServerStorage") local coilPass = 1234567 Players.PlayerAdded:Connect(function(player) local ok, owns = pcall(MarketplaceService.UserOwnsGamePassAsync, MarketplaceService, player.UserId, coilPass) if not ok or not owns then return end player.CharacterAdded:Connect(function() local backpack = player:WaitForChild("Backpack") local coil = ServerStorage.GravityCoil:Clone() coil.Parent = backpack end) end)
Fixed example
local MarketplaceService = game:GetService("MarketplaceService") local Players = game:GetService("Players") local ServerStorage = game:GetService("ServerStorage") local coilPass = 1234567 Players.PlayerAdded:Connect(function(player) local ok, owns = pcall(MarketplaceService.UserOwnsGamePassAsync, MarketplaceService, player.UserId, coilPass) if not ok or not owns then return end player.CharacterAdded:Connect(function() local backpack = player:WaitForChild("Backpack") local coil = ServerStorage.GravityCoil:Clone() :: Tool coil.CanBeDropped = false coil:SetAttribute("Owner", player.UserId) coil.Parent = backpack end) end)
The coil's own server script checks that the character holding it belongs to the player in its Owner attribute before it does anything.
Common false positives
- Free tools, such as a starting sword or a tool picked up from the map, can be dropped if the game wants that.
- Paid tools with
CanBeDroppedset tofalse, like the fixed example, are fine. - Gift and trade systems for paid tools are judged with Paid items traded with no policy check.