[v1.6.2] Luau Sandboxer

[v1.6.2] Luau Sandboxer

GitHub Source Documentation
Tests

A sandboxer that can help protect your game when running user-provided code.

Features

  • Sandbox scripts (provided the first line of code calls the sandbox - read here)
  • Sandbox functions
  • Customize allowed Instances in the InstanceList
  • Customize the sandbox environment (in Studio and at runtime)
  • Disallow certain classes of Instances from being instantiated with Instance.new and Instance.fromExisting
  • Hooking metamethods on Instances
  • Tracking created/accessed Instances & RBXScriptConnections for cleanup
  • More planned soon (including sandbox customization at runtime!)

Let me know if there is a specific feature you are looking for that the module does not currently offer! Any and all feedback is greatly appreciated.
Side note - if you’re looking to load a chunk without using the native loadstring function and sandbox it, use something like vLua or vLuau instead. This involves compiling the chunk to bytecode and executing it in a VM, which is not supported by this module

Security

If you find a security vulnerability or sandbox escape with the unmodified version of the module, please do not hesitate to DM me here on DevForum or on Discord (littlebitsman)!

Contributing

All contributions are welcome on GitHub! Look for issues with the “help wanted” tag to start.

(I haven’t written a README at time of writing this so uhh yeah)

What do you mean by "help protect my game?"

You are responsible for making sure that user code gets sandboxed. More info is in the documentation.

This is not an “end-all, be-all” module for making user code safe.

License

This module is licensed under the GNU AGPL v3.0 license.

This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Affero General Public License for more details.

What do you think of this as a community resource post? (rating)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
0 voters
Would you use this module, or recommend it to someone for a project?
  • yes
  • no
0 voters
14 Likes

Seems a very very great resource, keep it up like that!

Very cool module! But it appears that _G and shared are disabled, could setting them to an empty table work while staying sandboxed?

That probably could work but making that table shared would only be safe between sandboxed scripts (and it might have other caveats). I’ll probably implement it next update.

I think that they should not be shared across sandboxed scripts (or make it a setting) since part of sandboxing is making sure sandboxed scripts cannot interfere with other scripts (sandboxed & game-level).

Then it’s just as simple as doing this in a script:

local _G = {}
local shared = _G

Wait so it’s an actual Luau code runner, but sandboxed (technically similar to our-codes aswell)? This is great.

v1.1.0 Changelog

  • Added Sandboxer:SandboxString(src: string, chunkname: string): loads the string src as a Luau chunk with loadstring if enabled, sandboxes the function it returns, and returns it.
  • Fixed a bug in the sandboxed require implementation

Model got taken down, working to get it back up and get a .rbxm on GitHub.

EDIT: Model is back!

v1.2.0 Changelog

  • Exposed the InstanceList class in Sandboxer for easier editing of allowed Instances at runtime.
  • Added the Sandboxer.EditDefaultSandbox method which lets you edit the sandbox environment at runtime.

There are open-sourced loadstring components available online, such as through the Adonis Admin repository (which uses it in its commands, e.g. ;s print(game.GameId) would actually run the code and output to console even if loadstring is disabled.

It’s nothing major, however it’s a consideration to look into (I myself haven’t found out how they did it exactly).

I could look into that and add it. Though, if I remember correctly, Adonis is…big, to say the least. I’ll let you know if I get anything out of it.

EDIT: Looks like it compiles Luau to bytecode (using Yueliang), then executes it with a bytecode reader/executor (FiOne). Not sure if this is worth implementing for this project.

EDIT 2: The compiler in Luau for Luau takes up a TON of memory (30 MB).
image

I will add it, but have it only be require’d if native loadstring is unavailable. EDIT: NO LONGER PLANNED (It’s over 175k lines of code!) Here’s the GitHub link: GitHub - RadiatedExodus/LuauCeption: Running Luau inside Luau

Unfortunately, Roblox really does not like this model, so it will only be downloadable from GitHub from now on. (2 appeals denied :broken_heart:)

If anyone is looking for specific features, let me know!

I’m working on some stuff already for this (update soon hopefully)

v1.2.3 Changelog

  • Modified how Instance constructors are wrapped
  • fix internal types
  • change how references to Instances & RBXScriptSignals are kept
  • attempted to alphabetize functions in docs
  • added debug.setmemorycategory calls
1 Like

v1.2.5 Changelog

  • Fixed stack overflow in Instance metamethods caused by not using rawequal (oops)
  • Added :connect, :once, :wait, and :connectParallel as alternatives to their capitalized counterparts on wrapped RBXScriptSignals

v1.2.6 Changelog

  • Patched a sandbox escape that used BindableFunctions.

I strongly recommend updating to this version, especially if you are using this in a game.

1 Like

v1.3.2 Changelog

  • Added the ability to hook functions on Instances. For example you can make Players:BanAsync always fail within the sandbox. (Available in InstanceSandboxer)
  • Fixed some bugs, typos, & other stuff

sorry for the bump lols

v.1.3.3 changelog

  • Fixed “unreachable” when doing stuff like Signal + any - now correctly reports “failed to do add”
  • Added ForbiddenClasses to InstanceList that completely forbid them from being used anywhere in the sandbox, respecting inheritance (uses :IsA to check Instances). Any Instances that are forbidden become nil.
  • Default-enabled HttpService BUT made all network calls (GetAsync, PostAsync, RequestAsync, and GetSecret) always error. Allows for JSONEncode, JSONDecode, and GenerateGUID to be used.
1 Like

Sorry for the bump lols

v1.3.4 Changelog

  • fixed instanceAllowed not allowing parent = nil
  • fixed Instance.new + Instance.fromExisting (b/c prev change)
  • fixed some docs
  • created a test framework
1 Like