This method is likely subject to change as it uses an experimental feature.
Information in this post could get outdated at any day
Please be informed about Script capabilities | Documentation - Roblox Creator Hub
If you think that people can’t breach your sandbox and everything is safe now, Please think twice and check it a few more times.
The sandboxing model feature, while experimental and is lacking a lot of capability features, is already more than enough to make complete modding possible (even with a way to communicate with non-sandboxed functions, but I will talk about it later in this post)!
Unlike shenanigans with people using their own Lua vm just to execute the script, there is now a roblox’s way to do so, but 10 times better and with all LuaU optimizations (I think so)
This also should work in live experiences, as documentation says, although i would be careful with that because it’s experimental rn.
You need a moderation team for that that will approve ID of models. (or do so yourself)
So requirements is:
-
Someone must have access to https://create.roblox.com/dashboard/creations/experiences/ExpirienceIdHere/permissions
(assign someone you trust a lot) -
Modder (Person who is making mods for your game) must make Model public
-
You, as owner of the group, must get the model (The most annoying part)
-
You or someone in a group who has access to https://create.roblox.com/dashboard/creations/experiences/ExpirienceIdHere/permissions must give this model a permission.
-
Your game must have SignalBehavior set to Immiediate (security reasons + faster communication)
Sadly, there are no any other ways of inserting a model if these requirements are not followed; as of time, I’m writing this tutorial.
Sandboxing
To enable model sandboxing, you must toggle it from Default to Experimental
Now create a model in workspace that will be a container for scripts running there (or any inserted objects in general)
I will name it “Sandbox” and it will be a place where we put inserted scripts to.
Note: Script will get sandboxed only if it got compiled under this sandbox capability model and will inherit its capabilities there, so right After
InsertService:LoadAsset(IdHere)
parent it to this model (it can be a descendant of the model too)
For best safety, I would recommend you also do:
workspace.Sandbox.DescendantRemoving:Connect(function(ins)
if ins:IsDescendantOf(workspace.Sandbox) then return end
if ins:IsA("LuaSourceContainer") then
ins:Destroy()
end
end)
In case, script will try to breach the sandbox
Under Our “Sandbox” Model, make sure to toggle the “Sandboxed” property
Give it all capabilities that you think people should have 100% nonrestricted access to.
You can do a little bit of trolling by disabling those properties
Ok, all cool, but why I can’t access ReplicatedStorage and so how would I communicate with game scripts?
Short answer:
BindableFunctions and BindableEvents
You actually CAN use them as a sandboxed script if they are parented under sandbox!!!
Also note that they can be suddenly deleted by modder’s scripts, so be careful with that a lot, please!
From non-sandboxed environment, you can connect .Event or .OnInvoke easily, and the best part is that if you have done so from Outside the sandbox, you are able to call non-sandboxed functions inside the sandbox!
Pretty cool, right?
This way you can “access” this so-called “ReplicatedStorage” or so even though there is no such permission inside the native sandbox.
Also, please DON’T LET PEOPLE ACCESS DATASTORE DIRRECTLY!!! Always make a proxy with it in the BindableFunction
Well, all ways of implementation are up to you now that you know how to do modding.
I just show you a few examples:
Our workspace:
NON-SANDBOXED SCRIPT FROM SERVERSCRIPTSERVICE:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
workspace.Sandbox.Event.Event:Connect(function(...)
workspace.Sandbox:Destroy()
warn(...)
end)
workspace.Sandbox.Request.OnInvoke=function()
ReplicatedStorage.Folder:Destroy()
return
end
workspace.Sandbox.DescendantRemoving:Connect(function(ins)
if ins:IsDescendantOf(workspace.Sandbox) then return end
if ins:IsA("LuaSourceContainer") then
ins:Destroy()
end
end)
Modder’s script:
local event = workspace.Sandbox.Event
local Request = workspace.Sandbox.Request
--Communication with non sandboxed functions
Request:Invoke()
event:Fire(4,412,4,4)