We have a bug in Sumo Simulator where some calls to MarketplaceService:PromptProductPurchase throws the error “do not run what you just ran (vulnerable function)”.
We added debug logging to ensure that the player and the Developer Product ID to the call is correct,
The products are not “third party products” and “third party sales” is enabled either way.
The frequency of this happening in Sumo Simulator is about 2 times per minute and it is happening for multiple users. Purchases seems to work for a lot of users though (including us devs when we test)
-- Relevant code
local success, err = pcall(function()
MarketplaceService:PromptProductPurchase(player, p.Id)
end)
if not success then
local message = ("MarketplaceService:PromptProductPurchase failed, product: %s, player: %s, productId: %s, err: %s"):format(
tostring(name),
tostring(player),
tostring(p.Id),
tostring(err)
)
error(message)
end
Example output in the Error Report (correct player names hidden):
I have a feeling these errors come from exploit scripts… lots of exploit softwares have these kinds of safeguards in place to prevent their users from running malicious scripts that steal their Robux through these kinds of functions hopefully an engineer can confirm
Based on the error format and wording it’s more than likely an exploit one. Does a (temporary) change to how you handle product purchases still make the errors show up?
I just tested to fall back to the server calling PromptProductPurchase if it fails on the client, added some temporary logging to see if it works and it indicates that it actually shows the purchase to the exploiter.
Table containing suspicious errors:
local exploitEngineErrors = {
"do not run what you just ran (vulnerable function)."
}
Except from function module.PromptBuyProduct(player, name, buyCompletedCallback)
local success, err = pcall(function()
MarketplaceService:PromptProductPurchase(player, p.Id)
end)
if not success then
local isSuspiciousError = misc.TableContains(exploitEngineErrors, err)
if RunService:IsClient() then
if isSuspiciousError then
clientTriggeredSuspiciousError = true
warn("MarketplaceService:PromptProductPurchase threw suspicious error on client, attempting to run on server")
else
warn("MarketplaceService:PromptProductPurchase threw unknown error on client, attempting to run on server, err: " .. tostring(err))
end
promptBuyProductRemote:FireServer(name)
return
else
local message = ("MarketplaceService:PromptProductPurchase failed on server. product: %s, productId: %s, err: %s"):format(tostring(name), tostring(p.Id), tostring(err))
error(message)
end
end
clientTriggeredSuspiciousError = false
The logging part on the client:
MarketplaceService.PromptProductPurchaseFinished:Connect(function(userId, productId, isPurchased)
if clientTriggeredSuspiciousError then
warn("MarketplaceService:PromptProductPurchaseFinished after suspicious error, isPurchased: " .. tostring(isPurchased))
end
end)
Interesting. Keep in mind though, that exploiters can fire MarketplaceService.PromptProductPurchaseFinished at their own will, however many times they like (albeit the data returned by the function ex. isPurchased will still be correct). This is not very known about these MPS events.