Skip to main content

SafeGDScript

SafeGDScript lets you write GDScript that runs inside a sandbox. The source file uses the .sgd extension and standard GDScript syntax. On load the engine compiles it to RISC-V and executes it in a fully isolated virtual machine.

No Docker, no toolchain, no build step. Write .sgd, attach it to a node, and it runs sandboxed.

When to use SafeGDScript

  • Modding: let players add gameplay scripts without any access to the host
  • User-generated content: run uploaded code safely on a server or shared session
  • Hot-reloading logic: swap scripts at run-time without restarting the project
  • Cross-platform scripting: the compiled program runs everywhere Godot does, on all 20+ platforms

Quick start

Create a file with the .sgd extension (e.g. hello.sgd):

func hello(who : String) -> String:
return "Hello, " + who + "!"

func _ready():
print(hello("world"))

Attach it to a node using SafeGDScript:

var script := SafeGDScript.new()
script.set_source_code(FileAccess.get_file_as_string("res://hello.sgd"))

var node := Node.new()
node.set_script(script)
add_child(node)

When add_child is called the node enters the tree, _ready fires inside the sandbox, and the console prints Hello, world!.

Standard callbacks

SafeGDScript supports the same lifecycle callbacks as regular GDScript:

CallbackWhen it runs
_ready()Node enters the scene tree
_process(delta)Every frame
_physics_process(delta)Every physics tick

Restrictions

A SafeGDScript node is a regular Node with a sandboxed script. You control what the script can reach through the same restriction system used by all Godot Sandbox programs.

Enable full restrictions with a single property:

node.set("restrictions", true)

Once enabled, the sandbox denies all external access. The script can now only use what you pass to it, in function call arguments. See Restrictions & Isolation for fine-grained control.

Resource limits

Every sandbox instance exposes properties that cap its resource usage:

PropertyDefaultUnit
execution_timeout200Millions of instructions per call
memory_max32MB
allocations_max8000Outstanding allocations
references_max100Tracked object references
node.set("execution_timeout", 100)
node.set("memory_max", 16)

A script that exceeds its execution budget is stopped. The node stays loaded and subsequent calls still work.

Compared to C++ / Rust programs

SafeGDScript and compiled C++/Rust ELF programs share the same sandbox runtime. The trade-off is convenience vs. raw performance:

SafeGDScriptC++ / Rust ELF
Build stepOn-the-flyDocker / host toolchain
LanguageGDScript syntaxC++ or Rust
PerformanceGoodBest (+ binary translation)
Modding friendlinessHigh (familiar syntax)Lower (requires compiler)
Run-time loadingFrom text stringFrom ELF binary

For modding and UGC, SafeGDScript is the recommended path. For compute-heavy inner loops or when you need the full C++ ecosystem, use an ELF program.

Next steps