# Godot Sandbox: Running Untrusted Mods in SafeGDScript, C++, or Rust

> Godot Sandbox is a plugin that executes player-written code inside a memory-safe sandbox with timeouts and explicit API grants. It supports SafeGDScript, C++, and Rust, but the trade-offs in performance, setup, and debugging deserve scrutiny before adoption.

**libriscv/godot-sandbox** — In-editor scripting and sandboxing for Godot 4.4+

- Repository: https://github.com/libriscv/godot-sandbox
- Website: https://libriscv.no/docs/host_langs/godot_integration/godot_docs/design
- Stars: 491 · Forks: 22
- Language: C++
- License: BSD-3-Clause
- Published: 2026-08-24 · Updated: 2026-08-24 · Language: en
- Canonical page: https://hysenlabs.com/projects/libriscv-godot-sandbox

## What the Sandbox Actually Restricts

The core promise is that untrusted code cannot touch the host beyond what you explicitly allow. The README states that a restricted sandbox denies all host access by default, including methods, properties, classes, and resource loading. The gamedev passes an explicit API as a Dictionary to the mod's mod_init function. That API is the only bridge between sandboxed code and the engine. This is a capability-based model rather than a permission-list model. You do not toggle flags on a big settings screen; you construct the dictionary and hand it over. The design forces you to think about every callable, property, and signal that a mod can reach. That is a real shift from typical GDScript mod loaders where scripts run with full engine access. The documentation gives a small example where the mod receives log and report functions. It is clear, but the burden of designing a complete API for a complex game is on you. There is no built-in audit tool beyond the hostile-mod audit mentioned in the modding example, which lives in the examples directory, not in the core plugin.

## SafeGDScript: A Dialect with Structs and Await

SafeGDScript (.sgd) is the default language for sandboxed code. It keeps most GDScript syntax and adds structs, which GDScript itself lacks. The README shows a struct Item with typed fields and methods, including a nullable Vector2 and a union type int | Vector2. That is a meaningful extension for data-oriented gameplay code. It also supports await, as the cutscene example shows, where the script waits on a timer and then on a Signal passed from the host. The host can call that function and await the result like any coroutine. The syntax is close enough that attaching a .sgd file to a node mirrors attaching a .gd script. There is a VS Code extension for highlighting and basic support, but no mention of a debugger in the core plugin. The release notes for v0.51 mention profiling, debugging, and syntax polish for SafeGDScript, so debugging exists in some form, but the README does not detail it. Typed variables matter for performance, as the benchmark table shows a 5.36x speed advantage over GDScript for a specific dispatch case, but that is a microbenchmark, not a game-wide guarantee.

## C++ and Rust: Same Sandbox, Different Compile Path

For maximum performance, you can write sandboxed programs in C++ or Rust. They run in the same sandbox with the same restrictions. The README points to a separate code examples repository and a demo repository, but does not explain the compile workflow. The module build instructions show how to add the plugin as a Godot module via git submodule, which implies you need a C++ toolchain and SCons. The performance section claims sandboxed C++ is 2.5-10x faster than GDScript by default, and 5-50x with binary translation. Those numbers come from a linked benchmark page, not from a reproducible script in the repo. Binary translation is described as available on all platforms, including locked down ones like iOS and Switch, which is a strong claim. JIT builds are offered in Releases for Windows, macOS, Android, and Linux. That means you have two execution modes: interpreted and JIT, and the choice affects binary size, startup time, and platform certification. The documentation does not explain how to choose between them in a project, which is a gap for a practical adoption.

## Installation and First Steps

The README offers two installation paths. The automatic one uses the Godot Asset Library: open the AssetLib tab in Godot, search for Godot Sandbox, and download. The manual path is to grab the latest GitHub release and move only the addons folder into your project's addons folder. That is straightforward and matches how most Godot plugins are installed. After that, you attach a .sgd file to any node. There is no mention of a required Godot version beyond 4.4+, so you need a recent editor. For module builds, you run git submodule add and then git submodule update --init --recursive inside a Godot source tree. For contributing, you run ./build.sh or scons. The README does not show the exact scons command or how to configure the build for a specific platform. If you are not already comfortable with Godot's C++ build system, the module route is a barrier. The plugin is dual-use: it works as an editor plugin via the addons folder, and as a compiled module for deeper integration. The addon path is likely enough for most projects, but the performance claims for C++ and Rust probably assume the module build.

## Performance Claims and the Typed Variable Caveat

The benchmark table in the README compares SafeGDScript in the sandbox against GDScript in the engine. The numbers show 115.4 nanoseconds per emulated instruction for SafeGDScript versus 618.0 for GDScript, a 5.36x speedup. The note says using typed variables helps the compiler optimize. That is a concrete, testable claim, but it is one synthetic case. The modding example that implements a virtual CPU gained 5x over GDScript with typed variables. That is more convincing because it is a whole example, but it is still a single workload. The README also states that sandboxed C++ is 2.5-10x faster than GDScript by default, and 5-50x with binary translation. Those ranges are wide enough to invite skepticism. The actual performance you get depends on the mix of operations, the type annotations you write, and whether you enable binary translation. If your mods are mostly UI logic or low-frequency events, the speed difference will not matter. The overhead of running inside an emulated VM is always there, even if it is lower than GDScript's interpreter in these benchmarks. You should measure with your own gameplay code before assuming a win.

## Two Ways to Attach Sandboxed Scripts

The README describes two usage patterns. The first is to assign an ELF script resource directly to a node. This constructs a shared sandbox among all instances that use that script. The README claims maximum scalability, and you can call functions and attach signals like GDScript. The second pattern is to create a Sandbox node and assign the ELF resource to it. That gives one sandbox per node, with auto-completion from other GDScripts using @export. The choice matters. The shared sandbox saves memory and may be faster for many instances, but it also means all instances share state, which could be a problem if you want isolation between enemies or players. The per-node sandbox gives isolation but costs more resources. The README does not explain the trade-offs in detail. It also does not clarify what an ELF resource is in the editor workflow. You need to compile your C++ or Rust code to an ELF file and import it as a resource. That is not a typical Godot workflow, and the documentation link for the full usage is on the libriscv website, not in the README. For a team evaluating this, the two patterns are a key decision point, and the material gives only a high-level description.

## Modding Example and Hostile-Mod Audit

The README points to examples/modding for a complete mod loader with a hostile-mod audit. That is a valuable resource because it shows how to structure a real modding system. The example includes a mod_init function that receives a granted API dictionary, and a physics_process callback that calls a report function. The audit aspect is not described in the README beyond the name. You would need to read the example source to understand what checks it performs. The existence of an audit suggests that the plugin's default sandbox is not a complete security boundary by itself. You still need to review what your API exposes. The README says restricted programs cannot access the host beyond what you explicitly allow, but if you allow a method that has side effects, the mod can call it. The sandbox does not police the logic of your granted functions. That is a subtle but important limitation. The modding example is the best starting point for anyone serious about user-generated content, but it is not a drop-in solution. You must adapt it to your game's API and content model.

## Maintenance, License, and Upgrade Path

The project is under BSD-3-Clause, which is permissive and allows commercial use with attribution. The recent releases show active development: v0.53, v0.52, and v0.51 all landed within three days in August 2026. The release titles indicate a focus on SafeGDScript parity with GDScript, improved modding example, and profiling and debugging. That is a fast pace, which is good for bug fixes but also means the API may shift between versions. The README does not include a changelog or migration notes, so upgrading from an older version may require reading release notes on GitHub. The module build requires SCons and python3, and the build.sh script is the entry point for local builds. There is no mention of CI or test coverage in the README. The repository has a homepage with detailed documentation, but the README is thin on operational details like how to enable binary translation or how to set execution timeouts. You will need to consult the external docs. The plugin supports all Godot platforms, but the JIT builds are only listed for Windows, macOS, Android, and Linux. For iOS, Web, or Switch, you likely need the binary translation mode, which is a different setup. That is a practical constraint that is easy to miss.

## Conclusion

Adopt Godot Sandbox if you need to let players run mods or user-generated scripts in a Godot 4.4+ project and you are willing to learn SafeGDScript or accept the complexity of compiling C++ or Rust to ELF. Skip it if your modding community expects plain GDScript or if you cannot afford the debugging overhead of a separate language and VM. Before committing, verify that the plugin builds on your target platforms, especially mobile or console, and that your mod API design covers all the host resources you want to expose. Test the performance claims against your own workload, since the documented gains depend heavily on typed variables and binary translation.

## FAQ

### What is godot-sandbox?

A Godot 4.4 addon that lets players run untrusted code safely. Gameplay is written in SafeGDScript and executed inside a memory-safe sandbox with limits and execution timeouts, and C++ or Rust programs can be sandboxed with the same restrictions.

### How do I install godot-sandbox?

Either search for it in the AssetLib tab of the Godot editor and download it from the official asset store, or download the latest GitHub release and move only the addons folder into the project's addons folder. Moving the whole repository would import its examples and tests as game assets.

### Is SafeGDScript faster than GDScript?

The project gives 5.0 times with binary translation or JIT and 1.6 times in the interpreter. Its own table also notes that typed variables help the compiler optimise, citing a 5 times gain in a modding example that implements a virtual CPU.

### What does trait_structural_fallback do in godot-sandbox?

SafeGDScript traits are nominal for classes declared in the dialect, but foreign Godot objects can satisfy a trait structurally by providing its declared instance methods. Setting sandbox/safe_gdscript/trait_structural_fallback disables that compatibility path so matching stays strictly nominal.

### How do I run tests for sandboxed scripts?

Decorate the function with @test, then right-click the node or script in the editor for Run Tests or Run Test at Cursor, or run them all headlessly with godot --headless --path . pointing at the bundled test runner script.

## Sources

- [Official documentation](https://libriscv.no/docs/host_langs/godot_integration/godot_docs/design)
- [Official README](https://github.com/libriscv/godot-sandbox#readme)
- [Project repository](https://github.com/libriscv/godot-sandbox)
- [Release notes](https://github.com/libriscv/godot-sandbox/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/libriscv-godot-sandbox
