From bd8f311a960e0479d0100715120404efbbd8bfd2 Mon Sep 17 00:00:00 2001 From: architect-bot Date: Mon, 17 Aug 2026 20:52:21 +0000 Subject: [PATCH] Recovered orphaned WIP before switching to a new task --- sandbox_probe/probe5.gd | 99 +++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 59 deletions(-) diff --git a/sandbox_probe/probe5.gd b/sandbox_probe/probe5.gd index 1242944..46d2fa8 100644 --- a/sandbox_probe/probe5.gd +++ b/sandbox_probe/probe5.gd @@ -1,10 +1,7 @@ extends Node -# probe5.gd — Corrected, comprehensive sandboxing probe for Godot 4.6.2. -# Fixes the API-usage errors in earlier probes (static vs instance calls). - func _ready(): - print("=== SANDBOX PROBE 5: Corrected Sandboxing Mechanisms ===") + print("=== SANDBOX PROBE 5: Corrected Sandboxing Mechanisms (Godot 4.6.2) ===") probe_script_loading() probe_os_apis() probe_file_access() @@ -12,12 +9,11 @@ func _ready(): probe_classdb() probe_expression_engine() probe_engine_singletons() - probe_global_scope() probe_worker_threads() probe_project_settings() probe_scriptserver() probe_script_restrictions() - probe_subviewport_isolation() + probe_allowlist() print("=== SANDBOX PROBE 5 END ===") get_tree().quit() @@ -37,7 +33,7 @@ func probe_script_loading(): # Can we get the source code back from a loaded script? if res: print(" get_source_code() available: ", res.has_method("get_source_code")) - # Can we get the AST / parse tree? + # Can we get the AST / parse tree? (instance methods) print(" GDScript instance has 'get_ast': ", gd.has_method("get_ast")) print(" GDScript instance has 'get_parser': ", gd.has_method("get_parser")) # Can we get the list of methods? @@ -65,10 +61,6 @@ func probe_os_apis(): print("OS.get_user_data_dir() = ", OS.get_user_data_dir()) # Can we get executable path? print("OS.get_executable_path() = ", OS.get_executable_path()) - # Can we get the process ID? - print("OS has 'get_process_id': ", OS.has_method("get_process_id")) - # Can we kill processes? - print("OS has 'kill': ", OS.has_method("kill")) func probe_file_access(): print("--- File access ---") @@ -96,10 +88,6 @@ func probe_file_access(): print("DirAccess.open('res://') = ", res_dir) var user_dir = DirAccess.open("user://") print("DirAccess.open('user://') = ", user_dir) - # Can we use FileAccess.get_file_as_string? - print(" FileAccess has 'get_file_as_string': ", FileAccess.has_method("get_file_as_string")) - # Can we check if a file exists? - print(" FileAccess has 'file_exists': ", FileAccess.has_method("file_exists")) func probe_network(): print("--- Network ---") @@ -119,10 +107,6 @@ func probe_network(): # WebSocket var ws = WebSocketPeer.new() print("WebSocketPeer instantiated: ", ws != null) - # Can we connect to a remote host? - var http2 = HTTPClient.new() - var connect_err = http2.connect_to_host("example.com", 80) - print("HTTPClient.connect_to_host('example.com', 80) err=", connect_err) func probe_classdb(): print("--- ClassDB ---") @@ -143,7 +127,7 @@ func probe_classdb(): # Can we instantiate a class by name? var inst = ClassDB.instantiate("Node") print("ClassDB.instantiate('Node') = ", inst) - # Can we check if a class is a singleton? + # Can we check if a class is a singleton? (static method on ClassDB) print("ClassDB has 'class_get_singleton': ", ClassDB.has_method("class_get_singleton")) # Can we get the singleton instance of OS? var os_singleton = ClassDB.class_get_singleton("OS") @@ -152,10 +136,6 @@ func probe_classdb(): if os_singleton: print(" OS singleton has 'execute': ", os_singleton.has_method("execute")) print(" OS singleton has 'get_environment': ", os_singleton.has_method("get_environment")) - # Can we get the class list of a specific class? - print(" ClassDB has 'class_get_inheriters': ", ClassDB.has_method("class_get_inheriters")) - # Can we check if a class is an enum? - print(" ClassDB has 'class_get_enum_list': ", ClassDB.has_method("class_get_enum_list")) func probe_expression_engine(): print("--- Expression engine ---") @@ -194,17 +174,11 @@ func probe_expression_engine(): if err == OK: var result5 = expr5.execute() print(" Expression.execute() = ", result5) - # Can Expression access the global scope? - var expr6 = Expression.new() - err = expr6.parse("print('hello')") - print("Expression.parse('print') err=", err) - if err == OK: - var result6 = expr6.execute() - print(" Expression.execute() = ", result6) func probe_engine_singletons(): print("--- Engine singletons ---") # Engine singletons are the global objects like OS, Engine, etc. + # get_singletons() is a static method on Engine var singletons = Engine.get_singletons() print("Engine.get_singletons() count: ", singletons.size()) for s in singletons: @@ -215,26 +189,7 @@ func probe_engine_singletons(): # Can we get the main loop? print("Engine.get_main_loop() = ", Engine.get_main_loop()) # Can we get the physics server? - print("Engine has 'get_physics_server': ", Engine.has_method("get_physics_server")) - -func probe_global_scope(): - print("--- Global scope ---") - # Can we enumerate what's in the global scope? - var globals = [] - for g in GDScript.get_global_class_list(): - globals.append(g) - print("GDScript.get_global_class_list() count: ", globals.size()) - # Can we check if a global is available before using it? - print("GDScript has 'get_global_class_list': ", GDScript.has_method("get_global_class_list")) - # Is there any way to restrict which globals a script sees? - print("GDScript has 'set_global_scope': ", GDScript.has_method("set_global_scope")) - print("GDScript has 'restrict_globals': ", GDScript.has_method("restrict_globals")) - # Check the GDScript class methods - var methods = GDScript.get_method_list() - var method_names = [] - for m in methods: - method_names.append(m.name) - print(" GDScript methods: ", method_names) + print("Engine.get_physics_server() = ", Engine.get_physics_server()) func probe_worker_threads(): print("--- Worker threads ---") @@ -290,12 +245,38 @@ func probe_script_restrictions(): 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")) + print(" GDScript has method 'get_global_scope': ", gd.has_method("get_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_allowlist(): + print("--- Allowlist / static analysis ---") + # The allowlist approach: parse GDScript source and reject disallowed patterns + # Test: can we detect dangerous API calls via string analysis? + var dangerous_patterns = [ + "OS.execute", "OS.create_process", "OS.get_environment", + "FileAccess.open", "DirAccess.open", "TCPServer", "HTTPClient", + "load(", "preload(", "ClassDB", "Engine.get_main_loop", + "get_tree().quit", "ProjectSettings" + ] + var test_script = """extends Node +func _ready(): + var f = FileAccess.open("/etc/passwd", FileAccess.READ) + OS.execute("rm", ["-rf", "/"]) + """ + print(" Test script contains dangerous patterns:") + for p in dangerous_patterns: + if p in test_script: + print(" DETECTED: ", p) + # Can we use a tokenizer/lexer to parse GDScript? + # GDScript has a built-in tokenizer accessible via the language + var lang = GDScriptLanguage.new() + print(" GDScriptLanguage.new() = ", lang) + print(" GDScriptLanguage has 'get_name': ", lang.has_method("get_name")) + print(" GDScriptLanguage has 'get_extension': ", lang.has_method("get_extension")) + # Can we get the tokenizer? + print(" GDScriptLanguage has 'get_tokenizer': ", lang.has_method("get_tokenizer")) + # Can we get the parser? + print(" GDScriptLanguage has 'get_parser': ", lang.has_method("get_parser")) + # Can we get the analyzer? + print(" GDScriptLanguage has 'get_analyzer': ", lang.has_method("get_analyzer")) + # Can we get the compiler? + print(" GDScriptLanguage has 'get_compiler': ", lang.has_method("get_compiler"))