WIP checkpoint: Research and design GDScript sandboxing approach

This commit is contained in:
2026-08-17 20:33:56 +00:00
parent 62447258b2
commit a1846f34b5
+65 -60
View File
@@ -1,78 +1,83 @@
extends Node extends Node
func _ready(): func _ready():
print("=== SANDBOX PROBE 2: ScriptServer & Restrictions ===") print("=== SANDBOX PROBE 2: Sandboxing Mechanisms ===")
probe_scriptserver() probe_scriptserver()
probe_script_restrictions() probe_script_restrictions()
probe_subviewport_isolation()
probe_engine_restrictions() probe_engine_restrictions()
probe_global_scope() probe_allowlist_approach()
probe_classdb()
probe_script_extension()
print("=== SANDBOX PROBE 2 END ===") print("=== SANDBOX PROBE 2 END ===")
get_tree().quit() get_tree().quit()
func probe_scriptserver(): func probe_scriptserver():
print("--- ScriptServer ---") print("--- ScriptServer ---")
# Is ScriptServer available? It's a static class in Godot 4. # Does ScriptServer exist and what can it do?
print("ScriptServer exists: ", ClassDB.class_exists("ScriptServer")) print("ScriptServer has_method('get_language_count'): ", ScriptServer.has_method("get_language_count"))
if ClassDB.class_exists("ScriptServer"): print("ScriptServer has_method('get_language'): ", ScriptServer.has_method("get_language"))
# What methods does it expose? # Can we enumerate registered script languages?
var methods = ClassDB.class_get_method_list("ScriptServer") if ScriptServer.has_method("get_language_count"):
for m in methods: var count = ScriptServer.get_language_count()
print(" ScriptServer method: ", m.name, " args=", m.args.size()) print(" language count: ", count)
for i in range(count):
var lang = ScriptServer.get_language(i)
print(" language[", i, "] = ", lang)
func probe_script_restrictions(): func probe_script_restrictions():
print("--- Script restrictions ---") print("--- Script restrictions ---")
# Can we restrict script loading via ProjectSettings? # Can we restrict which classes/globals a script can access?
var keys = [ # Test: does GDScript have any built-in allowlist mechanism?
"debug/gdscript/warnings/", var gd = GDScript.new()
"debug/gdscript/", gd.source_code = "extends RefCounted\nfunc evil():\n\treturn OS.get_environment('HOME')\n"
"application/run/", var err = gd.reload()
] print(" GDScript with OS access reload err=", err)
for k in keys: if err == OK:
var settings = ProjectSettings.get_setting(k) var inst = gd.new()
print(" ProjectSettings['", k, "'] = ", settings) print(" evil() result: ", inst.call("evil"))
# Can we block specific global classes?
print(" GDScript has method to restrict globals: ", gd.has_method("set_global_scope"))
func probe_subviewport_isolation():
print("--- SubViewport isolation ---")
# SubViewports isolate rendering, but do they isolate script execution?
var vp = SubViewport.new()
print(" SubViewport.new() = ", vp)
# SubViewports share the same process/engine - scripts still have full access
print(" SubViewport does NOT isolate script execution (same process)")
vp.free()
func probe_engine_restrictions(): func probe_engine_restrictions():
print("--- Engine restrictions ---") print("--- Engine restrictions ---")
# Check if there's any sandbox/restriction setting # Is there a way to disable OS/File/Network access globally?
var all_settings = ProjectSettings.get_property_list() print(" Engine.has_singleton('OS'): ", Engine.has_singleton("OS"))
var sandbox_like = [] print(" Engine.has_singleton('FileAccess'): ", Engine.has_singleton("FileAccess"))
for s in all_settings: # Check if there's a '--disable-*' flag or project setting
var name = String(s.name) print(" ProjectSettings has 'application/run/disable_*': ", ProjectSettings.has_setting("application/run/disable_os"))
if "sandbox" in name.to_lower() or "restrict" in name.to_lower() or "security" in name.to_lower(): # Check for any sandbox-related project settings
sandbox_like.append(name) var settings = ProjectSettings.get_property_list()
print(" Sandbox/restrict/security settings found: ", sandbox_like) var sandbox_settings = []
for s in settings:
if "sandbox" in String(s.name).to_lower() or "restrict" in String(s.name).to_lower():
sandbox_settings.append(s.name)
print(" Sandbox-related project settings: ", sandbox_settings)
func probe_global_scope(): func probe_allowlist_approach():
print("--- Global scope ---") print("--- Allowlist approach ---")
# What global classes/functions are available to scripts? # The allowlist approach: parse GDScript source and reject disallowed patterns
# Check if we can enumerate global scope # Test: can we detect dangerous API calls via string analysis?
var global_classes = [] var dangerous_patterns = [
if ClassDB.class_exists("GlobalScope"): "OS.execute", "OS.create_process", "OS.get_environment",
var methods = ClassDB.class_get_method_list("GlobalScope") "FileAccess.open", "DirAccess.open", "TCPServer", "HTTPClient",
for m in methods: "load(", "preload(", "ClassDB", "Engine.get_main_loop",
global_classes.append(m.name) "get_tree().quit", "ProjectSettings"
print(" GlobalScope methods count: ", global_classes.size()) ]
# Key dangerous globals var test_script = """
var dangerous = ["OS", "FileAccess", "DirAccess", "TCPServer", "HTTPClient", "ProjectSettings", "Engine", "ResourceLoader", "ClassDB", "Expression", "JavaScriptBridge"] extends Node
for d in dangerous: func _ready():
print(" Class '", d, "' exists: ", ClassDB.class_exists(d)) var f = FileAccess.open("/etc/passwd", FileAccess.READ)
OS.execute("rm", ["-rf", "/"])
func probe_classdb(): """
print("--- ClassDB ---") print(" Test script contains dangerous patterns:")
# Can scripts access ClassDB to instantiate arbitrary classes? for p in dangerous_patterns:
print(" ClassDB.class_exists('Node') = ", ClassDB.class_exists("Node")) if p in test_script:
# Can we get all classes? print(" DETECTED: ", p)
var all_classes = ClassDB.get_class_list()
print(" ClassDB.get_class_list().size() = ", all_classes.size())
func probe_script_extension():
print("--- Script extension / custom interpreter ---")
# Check if ScriptExtension exists (for custom script languages)
print(" ScriptExtension exists: ", ClassDB.class_exists("ScriptExtension"))
# Check GDScript internals
print(" GDScript class exists: ", ClassDB.class_exists("GDScript"))
var gd_methods = ClassDB.class_get_method_list("GDScript")
for m in gd_methods:
print(" GDScript method: ", m.name)