84 lines
3.3 KiB
GDScript
84 lines
3.3 KiB
GDScript
extends Node
|
|
|
|
func _ready():
|
|
print("=== SANDBOX PROBE 2: Sandboxing Mechanisms ===")
|
|
probe_scriptserver()
|
|
probe_script_restrictions()
|
|
probe_subviewport_isolation()
|
|
probe_engine_restrictions()
|
|
probe_allowlist_approach()
|
|
print("=== SANDBOX PROBE 2 END ===")
|
|
get_tree().quit()
|
|
|
|
func probe_scriptserver():
|
|
print("--- ScriptServer ---")
|
|
# Does ScriptServer exist and what can it do?
|
|
print("ScriptServer has_method('get_language_count'): ", ScriptServer.has_method("get_language_count"))
|
|
print("ScriptServer has_method('get_language'): ", ScriptServer.has_method("get_language"))
|
|
# Can we enumerate registered script languages?
|
|
if ScriptServer.has_method("get_language_count"):
|
|
var count = ScriptServer.get_language_count()
|
|
print(" language count: ", count)
|
|
for i in range(count):
|
|
var lang = ScriptServer.get_language(i)
|
|
print(" language[", i, "] = ", lang)
|
|
|
|
func probe_script_restrictions():
|
|
print("--- Script restrictions ---")
|
|
# Can we restrict which classes/globals a script can access?
|
|
# Test: does GDScript have any built-in allowlist mechanism?
|
|
var gd = GDScript.new()
|
|
gd.source_code = "extends RefCounted\nfunc evil():\n\treturn OS.get_environment('HOME')\n"
|
|
var err = gd.reload()
|
|
print(" GDScript with OS access reload err=", err)
|
|
if err == OK:
|
|
var inst = gd.new()
|
|
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():
|
|
print("--- Engine restrictions ---")
|
|
# Is there a way to disable OS/File/Network access globally?
|
|
print(" Engine.has_singleton('OS'): ", Engine.has_singleton("OS"))
|
|
print(" Engine.has_singleton('FileAccess'): ", Engine.has_singleton("FileAccess"))
|
|
# Check if there's a '--disable-*' flag or project setting
|
|
print(" ProjectSettings has 'application/run/disable_*': ", ProjectSettings.has_setting("application/run/disable_os"))
|
|
# Check for any sandbox-related project settings
|
|
var settings = ProjectSettings.get_property_list()
|
|
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_allowlist_approach():
|
|
print("--- Allowlist approach ---")
|
|
# 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)
|