test_sandbox.lua (6043B)
1 -- Test file for OrbitManager.newSandbox 2 3 local OrbitManager = require("OrbitManager") 4 5 print("=== OrbitManager.newSandbox Test Suite ===\n") 6 7 -- Test manifest 8 local manifestString = [[ 9 return { 10 name = "sandboxedapp"; 11 dev = "testdev"; 12 perms = { 13 fs = true, 14 os = false, 15 network = false 16 }; 17 allowedPaths = { 18 "/tmp/*", 19 "/home/user/data/*" 20 }; 21 allowedDomains = { 22 "api.example.com" 23 } 24 } 25 ]] 26 27 -- Test 1: Create a sandbox 28 print("1. Creating sandbox with OrbitManager.newSandbox...") 29 local orbit, sandbox = OrbitManager.newSandbox(manifestString) 30 print(" ✓ Sandbox created successfully\n") 31 32 -- Test 2: Check that safe functions are available 33 print("2. Testing safe functions in sandbox...") 34 print(" print available:", type(sandbox.print)) 35 print(" string.upper available:", type(sandbox.string.upper)) 36 print(" math.sin available:", type(sandbox.math.sin)) 37 print(" table.insert available:", type(sandbox.table.insert)) 38 print(" ✓ Safe functions are accessible\n") 39 40 -- Test 3: Check that dangerous functions are blocked 41 print("3. Testing that dangerous functions are blocked...") 42 print(" debug library:", type(sandbox.debug)) 43 print(" loadfile:", type(sandbox.loadfile)) 44 print(" dofile:", type(sandbox.dofile)) 45 print(" ✓ Dangerous functions are nil (blocked)\n") 46 47 -- Test 4: Check that permission-controlled functions exist but are stubbed 48 print("4. Testing permission-controlled functions...") 49 print(" io.open available:", type(sandbox.io.open)) 50 print(" os.execute available:", type(sandbox.os.execute)) 51 print(" os.clock available:", type(sandbox.os.clock)) 52 print() 53 54 -- Test 5: Try to use io.open with permissions granted 55 print("5. Testing io.open with fs permissions (should work for allowed paths)...") 56 local success, err = pcall(function() 57 -- This should work because perms.fs = true and /tmp/* is allowed 58 sandbox.io.open("/tmp/test.txt", "r") 59 end) 60 if success then 61 print(" ✓ io.open('/tmp/test.txt') succeeded") 62 else 63 print(" ✗ io.open failed:", err) 64 end 65 66 success, err = pcall(function() 67 -- This should fail because /etc/passwd is not in allowedPaths 68 sandbox.io.open("/etc/passwd", "r") 69 end) 70 if not success then 71 print(" ✓ io.open('/etc/passwd') blocked:", err) 72 else 73 print(" ✗ FAILED: Should have blocked /etc/passwd") 74 end 75 print() 76 77 -- Test 6: Try to use os.execute without permissions 78 print("6. Testing os.execute without os permissions (should fail)...") 79 success, err = pcall(function() 80 sandbox.os.execute("ls") 81 end) 82 if not success then 83 print(" ✓ os.execute blocked:", err) 84 else 85 print(" ✗ FAILED: Should have blocked os.execute") 86 end 87 print() 88 89 -- Test 7: Test safe string operations in sandbox 90 print("7. Testing safe operations in sandbox...") 91 local testCode = [[ 92 local str = "hello world" 93 local upper = string.upper(str) 94 local result = string.sub(upper, 1, 5) 95 return result 96 ]] 97 98 local chunk, compileErr = load(testCode, "testCode", "t", sandbox) 99 if chunk then 100 local ok, result = pcall(chunk) 101 if ok then 102 print(" ✓ Sandbox code executed successfully, result:", result) 103 else 104 print(" ✗ Sandbox code failed:", result) 105 end 106 else 107 print(" ✗ Failed to compile:", compileErr) 108 end 109 print() 110 111 -- Test 8: Test that sandbox cannot access global _G 112 print("8. Testing sandbox isolation from global environment...") 113 local isolationTest = [[ 114 -- Try to access something from the real _G (should not be possible) 115 -- The sandbox _G should point to itself, not the real global 116 return _G == _ENV 117 ]] 118 119 chunk, compileErr = load(isolationTest, "isolationTest", "t", sandbox) 120 if chunk then 121 local ok, result = pcall(chunk) 122 print(" Sandbox _G == _ENV:", result) 123 print(" ✓ Sandbox has its own _G\n") 124 end 125 126 -- Test 9: Test that blocked functions really don't exist 127 print("9. Testing execution of code that tries to use blocked functions...") 128 local blockedTest = [[ 129 if debug then 130 return "FAIL: debug should be blocked" 131 end 132 if loadfile then 133 return "FAIL: loadfile should be blocked" 134 end 135 return "SUCCESS: blocked functions are nil" 136 ]] 137 138 chunk, compileErr = load(blockedTest, "blockedTest", "t", sandbox) 139 if chunk then 140 local ok, result = pcall(chunk) 141 print(" " .. (result or "error")) 142 end 143 print() 144 145 -- Test 10: Test math and table operations 146 print("10. Testing math and table operations in sandbox...") 147 local mathTest = [[ 148 local nums = {1, 5, 3, 9, 2} 149 table.sort(nums) 150 local sum = 0 151 for i = 1, #nums do 152 sum = sum + nums[i] 153 end 154 return sum, math.sqrt(sum) 155 ]] 156 157 chunk, compileErr = load(mathTest, "mathTest", "t", sandbox) 158 if chunk then 159 local ok, sum, sqrt = pcall(chunk) 160 if ok then 161 print(" ✓ Math operations work: sum =", sum, "sqrt =", sqrt) 162 else 163 print(" ✗ Failed:", sum) 164 end 165 end 166 print() 167 168 -- Test 11: Create another sandbox with different permissions 169 print("11. Testing second sandbox with OS permissions but no FS...") 170 local manifest2 = [[ 171 return { 172 name = "ostool"; 173 dev = "admin"; 174 perms = { 175 fs = false, 176 os = true 177 }; 178 allowedPaths = {}; 179 allowedDomains = {} 180 } 181 ]] 182 183 local orbit2, sandbox2 = OrbitManager.newSandbox(manifest2) 184 print(" Created second sandbox") 185 186 success, err = pcall(function() 187 sandbox2.os.clock() 188 end) 189 if success then 190 print(" ✓ os.clock works with os permissions") 191 else 192 print(" ✗ os.clock failed:", err) 193 end 194 195 success, err = pcall(function() 196 sandbox2.io.open("/tmp/test.txt", "r") 197 end) 198 if not success then 199 print(" ✓ io.open blocked without fs permissions:", err) 200 else 201 print(" ✗ FAILED: Should have blocked io.open") 202 end 203 print() 204 205 -- Test 12: Test getSandbox method 206 print("12. Testing getSandbox method...") 207 local retrievedSandbox = orbit:getSandbox() 208 print(" getSandbox returned:", type(retrievedSandbox)) 209 print(" Same as original sandbox:", retrievedSandbox == sandbox) 210 print() 211 212 print("=== All Tests Complete ===")