23 KiB
Sandbox Implementation Milestones
Based on SANDBOX.md design document. Implementation order optimized for dependencies.
Milestone 1: Core Sandbox Foundation ✅
Status: Complete Goal: Create isolated Lua environments with resource limits. Estimated Files: 3 new files
Deliverables
| Component | File | Description |
|---|---|---|
| LuaSandbox class | src/main/cpp/sandbox/lua_sandbox.h |
Main sandbox container |
| Custom allocator | src/main/cpp/sandbox/lua_sandbox.cpp |
Per-app memory tracking/limits |
| Instruction hook | src/main/cpp/sandbox/lua_sandbox.cpp |
CPU limit enforcement |
| Globals removal | src/main/cpp/sandbox/lua_sandbox.cpp |
Remove os, io, debug, etc. |
| Bytecode prevention | src/main/cpp/sandbox/lua_sandbox.cpp |
Text-only loading mode |
| Metatable protection | src/main/cpp/sandbox/lua_sandbox.cpp |
Freeze _G and string metatable |
Implementation Tasks
-
Create
LuaSandboxclass with:lua_State* m_L- isolated stateSandboxLimits m_limits- memory/CPU/stack limitsSandboxContext m_context- app_id, permissions, etc.- Custom allocator that tracks
m_memory_used
-
Implement
RemoveDangerousGlobals():- Remove:
os,io,debug,package,require,ffi,jit - Remove:
dofile,loadfile,load,loadstring - Remove:
rawget,rawset,rawequal,rawlen - Remove:
collectgarbage,newproxy - Remove:
string.dump
- Remove:
-
Implement instruction hook:
lua_sethook(L, InstructionHook, LUA_MASKCOUNT, 1000)- Throw error when limit exceeded
-
Implement
ProtectBuiltinTables():- Set
__metatableon string metatable - Freeze
_Gwith__newindexerror
- Set
Dependencies
- Lua library already linked (via RmlUi)
Test Criteria
TEST(LuaSandbox, DangerousGlobalsRemoved);
TEST(LuaSandbox, BytecodeRejected);
TEST(LuaSandbox, MemoryLimitEnforced);
TEST(LuaSandbox, CPULimitEnforced);
TEST(LuaSandbox, MetatableProtected);
Milestone 2: Permission System ✅
Status: Complete Goal: Gate API access based on app permissions. Estimated Files: 2 new files
Deliverables
| Component | File | Description |
|---|---|---|
| PermissionGate | src/main/cpp/sandbox/permission_gate.h |
Permission checking |
| User gesture tracking | src/main/cpp/sandbox/permission_gate.cpp |
Recent tap/click detection |
| Permission categories | src/main/cpp/sandbox/permission_gate.cpp |
Normal/Dangerous/Signature |
Implementation Tasks
-
Define permission categories:
enum class PermissionCategory { Normal, Dangerous, Signature }; -
Create
PermissionGateclass:bool Check(lua_State* L, const std::string& permission)int RequirePermission(lua_State* L, const char* perm)- throws Lua error
-
Implement user gesture tracking:
void RecordUserGesture()- called on touch downbool HasRecentUserGesture(int ms)- check within time window
-
Define permission manifest parsing:
- Read
manifest.jsonfrom app package - Extract
permissionsarray
- Read
Dependencies
- Milestone 1 (LuaSandbox)
Test Criteria
TEST(PermissionGate, NormalPermissionAutoGranted);
TEST(PermissionGate, DangerousPermissionRequiresGrant);
TEST(PermissionGate, SignaturePermissionSystemOnly);
TEST(PermissionGate, UserGestureRequired);
Milestone 3: Audit Logging & Rate Limiting ✅
Status: Complete Goal: Track security events and prevent API abuse. Estimated Files: 2 new files
Deliverables
| Component | File | Description |
|---|---|---|
| AuditLog | src/main/cpp/sandbox/audit_log.h/cpp |
Security event logging |
| RateLimiter | src/main/cpp/sandbox/rate_limiter.h/cpp |
Token bucket rate limiting |
Implementation Tasks
-
Create
AuditLogclass:enum class AuditEvent { AppStart, AppStop, PermissionCheck, PermissionDenied, NetworkRequest, FileAccess, SandboxViolation, ResourceLimitHit }; -
Implement thread-safe logging:
- Ring buffer with max entries
- Log critical events to Android logcat
-
Create
RateLimiterclass:- Token bucket algorithm
- Per-operation limits:
network.request,storage.write, etc. bool Check(const std::string& app_id, const std::string& operation)
Dependencies
- Milestone 1 (LuaSandbox)
Test Criteria
TEST(AuditLog, LogsSecurityEvents);
TEST(AuditLog, ThreadSafe);
TEST(RateLimiter, EnforcesLimits);
TEST(RateLimiter, RefillsOverTime);
Milestone 4: Safe Path & Require ✅
Status: Complete Goal: Secure file access within app sandbox. Estimated Files: 1 new file
Deliverables
| Component | File | Description |
|---|---|---|
| Path validation | src/main/cpp/sandbox/path_sandbox.h/cpp |
Canonical path checking |
| Safe require | src/main/cpp/sandbox/path_sandbox.cpp |
Module loader from app/scripts/ |
Implementation Tasks
-
Implement
ValidatePath():- Reject
..traversal - Reject absolute paths
- Canonicalize and verify prefix match
- Reject
-
Implement
SafeRequire():- Validate module name (alphanumeric + underscore)
- Load from
app_path/scripts/name.lua - Cache in registry
__loaded - Text-only mode (
"t")
-
Register as global
require:lua_pushcfunction(L, SafeRequire); lua_setglobal(L, "require");
Dependencies
- Milestone 1 (LuaSandbox)
Test Criteria
TEST(PathSandbox, RejectsTraversal);
TEST(PathSandbox, RejectsAbsolutePaths);
TEST(SafeRequire, LoadsFromScriptsDir);
TEST(SafeRequire, CachesModules);
Milestone 5: Timer & Callback System ✅
Status: Complete Goal: Safe timer APIs managed by kernel. Estimated Files: 1 new file
Deliverables
| Component | File | Description |
|---|---|---|
| TimerManager | src/main/cpp/sandbox/timer_manager.h/cpp |
setTimeout/setInterval |
Implementation Tasks
-
Create
TimerManagerclass:- Priority queue of pending timers
- Per-app timer limits (max 100)
- Minimum 10ms granularity
-
Implement Lua APIs:
setTimeout(callback, ms) -> id clearTimeout(id) setInterval(callback, ms) -> id clearInterval(id) -
Integrate with kernel main loop:
- Check and fire timers each frame
- Reset instruction count before callback
-
Implement cleanup:
ClearAppTimers(app_id)on app stop
Dependencies
- Milestone 1 (LuaSandbox)
- Milestone 3 (RateLimiter)
Test Criteria
TEST(TimerManager, FiresTimeout);
TEST(TimerManager, FiresInterval);
TEST(TimerManager, LimitsPerApp);
TEST(TimerManager, CleansUpOnStop);
Milestone 6: JSON & Crypto APIs ✅
Status: Complete Goal: Safe data parsing and cryptographic primitives. Estimated Files: 2 new files
Deliverables
| Component | File | Description |
|---|---|---|
| JSON API | src/main/cpp/sandbox/json_api.cpp |
Safe encode/decode |
| Crypto API | src/main/cpp/sandbox/crypto_api.cpp |
Hash, random, HMAC |
Implementation Tasks
-
Implement
json.decode():- Depth limit (32)
- String length limit (1 MB)
- Array/object size limits
-
Implement
json.encode():- Cycle detection
- Output size limit
-
Implement crypto APIs:
crypto.randomBytes(n)- CSPRNGcrypto.hash("sha256", data)crypto.hmac("sha256", key, data)- Remove
math.randomseed, replacemath.randomwith per-app RNG
Dependencies
- Milestone 1 (LuaSandbox)
- nlohmann-json (already in vcpkg)
Test Criteria
TEST(JsonApi, DecodesValid);
TEST(JsonApi, RejectsDeepNesting);
TEST(JsonApi, RejectsTooLarge);
TEST(CryptoApi, RandomBytesSecure);
TEST(CryptoApi, HashCorrect);
Milestone 7: Virtual Filesystem ✅
Status: Complete Goal: Per-app isolated storage with quotas. Estimated Files: 1 new file
Deliverables
| Component | File | Description |
|---|---|---|
| VirtualFS | src/main/cpp/sandbox/virtual_fs.h/cpp |
App storage API |
Implementation Tasks
-
Define virtual path mapping:
/data/ → /data/data/com.omixlab.mosis/apps/<app_id>/data/ /cache/ → /data/data/com.omixlab.mosis/apps/<app_id>/cache/ /temp/ → (session-only, cleared on stop) /shared/ → requires storage.shared permission -
Implement Lua file API:
fs.read(path) -> string fs.write(path, data) -> bool fs.append(path, data) -> bool fs.delete(path) -> bool fs.exists(path) -> bool fs.list(dir) -> table fs.mkdir(path) -> bool fs.stat(path) -> {size, modified, isDir} -
Enforce limits:
- Per-app quota (50 MB default)
- Max file size (10 MB)
- Max path depth (10)
-
Cleanup
/temp/on app stop.
Dependencies
- Milestone 1 (LuaSandbox)
- Milestone 2 (PermissionGate)
- Milestone 4 (Path validation)
Test Criteria
TEST(VirtualFS, ReadsWritesInAppDir);
TEST(VirtualFS, BlocksTraversal);
TEST(VirtualFS, EnforcesQuota);
TEST(VirtualFS, CleansUpTemp);
Milestone 8: SQLite Database ✅
Status: Complete Goal: Per-app SQLite with injection prevention. Estimated Files: 1 new file
Deliverables
| Component | File | Description |
|---|---|---|
| DatabaseManager | src/main/cpp/sandbox/database_manager.h/cpp |
SQLite sandbox |
Implementation Tasks
-
Create per-app database:
- Location:
/data/data/com.omixlab.mosis/apps/<app_id>/db/app.db - Max database size: 50 MB
- Location:
-
Implement SQLite authorizer:
sqlite3_set_authorizer(db, Authorizer, sandbox); // Block: ATTACH, DETACH, dangerous PRAGMAs, load_extension -
Implement Lua API:
local db = database.open("mydata") db:execute("CREATE TABLE IF NOT EXISTS items (id INTEGER PRIMARY KEY, name TEXT)") db:execute("INSERT INTO items (name) VALUES (?)", {"Item 1"}) local rows = db:query("SELECT * FROM items WHERE id > ?", {0}) db:close() -
Enforce prepared statements only (no raw SQL interpolation).
Dependencies
- Milestone 1 (LuaSandbox)
- Milestone 2 (PermissionGate)
- SQLite3 (add to vcpkg)
Test Criteria
TEST(Database, CreatesTables);
TEST(Database, PreparedStatements);
TEST(Database, BlocksAttach);
TEST(Database, BlocksDangerousPragma);
Milestone 9: Network - HTTP ✅
Status: Complete Goal: Secure HTTP requests with domain filtering. Estimated Files: 2 new files
Deliverables
| Component | File | Description |
|---|---|---|
| HttpRequestValidator | src/main/cpp/sandbox/http_validator.h/cpp |
URL/domain validation |
| NetworkManager | src/main/cpp/sandbox/network_manager.h/cpp |
HTTP client wrapper |
Implementation Tasks
-
Implement URL parsing and validation:
- Require HTTPS
- Block private IPs, localhost, metadata IPs
- Domain whitelist from manifest
-
Implement Lua HTTP API:
local response = network.request({ url = "https://api.example.com/data", method = "POST", headers = {...}, body = "...", timeout = 30000 }) -
Integrate with Android HttpURLConnection or libcurl.
-
Enforce limits:
- Request body: 10 MB
- Response body: 50 MB
- Timeout: 60s
- Concurrent requests: 6
Dependencies
- Milestone 1 (LuaSandbox)
- Milestone 2 (PermissionGate)
- Milestone 3 (RateLimiter, AuditLog)
Test Criteria
TEST(HttpValidator, BlocksPrivateIP);
TEST(HttpValidator, BlocksLocalhost);
TEST(HttpValidator, RequiresHttps);
TEST(HttpValidator, EnforcesDomainWhitelist);
TEST(NetworkManager, MakesRequest);
Milestone 10: Network - WebSocket ✅
Status: Complete Goal: Secure WebSocket connections. Estimated Files: 1 new file (extends NetworkManager)
Deliverables
| Component | File | Description |
|---|---|---|
| WebSocketManager | src/main/cpp/sandbox/websocket_manager.h/cpp |
WS connections |
Implementation Tasks
-
Implement connection management:
- Max 5 connections per app
- Idle timeout: 5 minutes
- Message size limit: 1 MB
-
Implement Lua WebSocket API:
local ws = network.websocket("wss://api.example.com/ws") ws:on("open", function() ... end) ws:on("message", function(data) ... end) ws:on("close", function(code, reason) ... end) ws:send(data) ws:close() -
Use same URL validation as HTTP.
-
Cleanup connections on app stop.
Dependencies
- Milestone 9 (HttpRequestValidator)
Test Criteria
TEST(WebSocketManager, Connects);
TEST(WebSocketManager, LimitsPerApp);
TEST(WebSocketManager, CleansUpOnStop);
Milestone 11: Virtual Hardware - Camera ✅
Status: Complete Goal: Camera access with mandatory indicators. Estimated Files: 1 new file
Deliverables
| Component | File | Description |
|---|---|---|
| CameraInterface | src/main/cpp/sandbox/camera_interface.h/cpp |
Camera API |
Implementation Tasks
-
Implement session management:
startSession(options)- requires permission + user gesturecapturePhoto()- returns frame datastopSession()
-
Mandatory recording indicator:
- Show in system UI (cannot be hidden by app)
-
Implement Lua API:
local session = camera.start({facing = "back", resolution = "720p"}) session:on("frame", function(data) ... end) local photo = session:capture() session:stop() -
Rate limit: 1 session at a time, max 30 fps.
Dependencies
- Milestone 2 (PermissionGate + user gesture)
- Milestone 3 (AuditLog)
- Game engine camera bridge (future)
Test Criteria
TEST(CameraInterface, RequiresPermission);
TEST(CameraInterface, RequiresUserGesture);
TEST(CameraInterface, ShowsIndicator);
TEST(CameraInterface, StopsOnAppStop);
Milestone 12: Virtual Hardware - Microphone ✅
Status: Complete Goal: Audio recording with mandatory indicators. Estimated Files: 1 new file
Deliverables
| Component | File | Description |
|---|---|---|
| MicrophoneInterface | src/main/cpp/sandbox/microphone_interface.h/cpp |
Mic API |
Implementation Tasks
-
Implement recording session:
startRecording(options)- requires permission + user gesturestopRecording()- returns audio data
-
Mandatory recording indicator (same as camera).
-
Implement Lua API:
local recording = microphone.start({sampleRate = 44100, channels = 1}) recording:on("data", function(samples) ... end) local audio = recording:stop() -
Rate limit: 1 recording at a time.
Dependencies
- Milestone 2 (PermissionGate + user gesture)
- Milestone 3 (AuditLog)
Test Criteria
TEST(MicrophoneInterface, RequiresPermission);
TEST(MicrophoneInterface, RequiresUserGesture);
TEST(MicrophoneInterface, ShowsIndicator);
Milestone 13: Virtual Hardware - Audio Output ✅
Status: Complete Goal: Safe audio playback. Estimated Files: 1 new file
Deliverables
| Component | File | Description |
|---|---|---|
| AudioOutputInterface | src/main/cpp/sandbox/audio_output.h/cpp |
Speaker API |
Implementation Tasks
-
Implement playback:
play(audioData, options)stop()setVolume(0.0-1.0)
-
System volume limit (app cannot exceed system volume).
-
Implement Lua API:
local player = audio.play(soundData, {loop = false, volume = 0.8}) player:on("ended", function() ... end) player:stop() -
Concurrent sound limit: 10 per app.
Dependencies
- Milestone 1 (LuaSandbox)
Test Criteria
TEST(AudioOutput, PlaysSound);
TEST(AudioOutput, RespectsVolumeLimit);
TEST(AudioOutput, LimitsConcurrent);
Milestone 14: Virtual Hardware - Location ✅
Status: Complete Goal: Location with privacy controls. Estimated Files: 1 new file
Deliverables
| Component | File | Description |
|---|---|---|
| LocationInterface | src/main/cpp/sandbox/location_interface.h/cpp |
GPS API |
Implementation Tasks
-
Two permission levels:
location.coarse- city-level (1km accuracy)location.fine- precise GPS
-
Implement Lua API:
location.getCurrentPosition(function(pos) print(pos.latitude, pos.longitude, pos.accuracy) end) local watch = location.watchPosition(function(pos) ... end, { enableHighAccuracy = true, timeout = 30000 }) watch:stop() -
Rate limit: 1 request per second.
-
Reduce precision for coarse permission.
Dependencies
- Milestone 2 (PermissionGate)
- Milestone 3 (RateLimiter)
Test Criteria
TEST(LocationInterface, RequiresPermission);
TEST(LocationInterface, CoarseReducesPrecision);
TEST(LocationInterface, RateLimits);
Milestone 15: Virtual Hardware - Sensors ✅
Status: Complete Goal: Motion sensors with fingerprinting prevention. Estimated Files: 1 new file
Deliverables
| Component | File | Description |
|---|---|---|
| SensorInterface | src/main/cpp/sandbox/sensor_interface.h/cpp |
Accelerometer, gyro, etc. |
Implementation Tasks
-
Supported sensors:
- Accelerometer (requires
sensors.motion) - Gyroscope (requires
sensors.motion) - Magnetometer (requires
sensors.motion) - Proximity (auto-granted)
- Ambient light (auto-granted)
- Accelerometer (requires
-
Implement Lua API:
local sub = sensors.subscribe("accelerometer", function(data) print(data.x, data.y, data.z, data.timestamp) end, {frequency = 60}) sub:stop() -
Reduce precision to prevent fingerprinting:
- Round values to 2 decimal places
- Limit update frequency to 60 Hz
Dependencies
- Milestone 2 (PermissionGate)
Test Criteria
TEST(SensorInterface, RequiresPermission);
TEST(SensorInterface, ReducesPrecision);
TEST(SensorInterface, LimitsFrequency);
Milestone 16: Virtual Hardware - Bluetooth ✅
Status: Complete
Goal: Bluetooth discovery and pairing. Estimated Files: 1 new file
Deliverables
| Component | File | Description |
|---|---|---|
| BluetoothInterface | src/main/cpp/sandbox/bluetooth_interface.h/cpp |
BT API |
Implementation Tasks
-
Discovery with user consent:
startDiscovery()requires user confirmation- Return device name/address only (no full UUID list)
-
Implement Lua API:
bluetooth.startDiscovery(function(devices) for _, device in ipairs(devices) do print(device.name, device.address) end end, {timeout = 30}) bluetooth.connect(address, function(connection) connection:send(data) end) -
Limit: 5 connections per app.
Dependencies
- Milestone 2 (PermissionGate + user gesture)
Test Criteria
TEST(BluetoothInterface, RequiresPermission);
TEST(BluetoothInterface, RequiresUserConsent);
Milestone 17: Virtual Hardware - Contacts
Goal: Contact access with granular permissions. Estimated Files: 1 new file
Deliverables
| Component | File | Description |
|---|---|---|
| ContactsInterface | src/main/cpp/sandbox/contacts_interface.h/cpp |
Contacts API |
Implementation Tasks
-
Separate read/write permissions:
contacts.read- query contactscontacts.write- add/modify contacts
-
Implement Lua API:
local contacts = contacts.query({search = "John"}) for _, c in ipairs(contacts) do print(c.name, c.phone, c.email) end contacts.add({name = "New Contact", phone = "555-1234"}) -
Limit fields returned (no raw account data).
Dependencies
- Milestone 2 (PermissionGate)
Test Criteria
TEST(ContactsInterface, RequiresReadPermission);
TEST(ContactsInterface, RequiresWritePermission);
Milestone 18: Inter-App Communication
Goal: Kernel-mediated message passing. Estimated Files: 1 new file
Deliverables
| Component | File | Description |
|---|---|---|
| MessageBus | src/main/cpp/sandbox/message_bus.h/cpp |
App-to-app messaging |
Implementation Tasks
-
Implement intent system:
- Manifest declares received intents
- Sender must have required permissions
-
Implement Lua API:
-- Sending intents.send({ action = "share", type = "text/plain", data = "Hello world" }) -- Receiving (in manifest + handler) intents.on("share", function(intent) print(intent.from, intent.data) end) -
Validate sender/receiver at runtime.
Dependencies
- Milestone 2 (PermissionGate)
- Milestone 3 (AuditLog)
Test Criteria
TEST(MessageBus, SendsToRegisteredReceiver);
TEST(MessageBus, BlocksUnregisteredAction);
Milestone 19: Security Testing Suite
Goal: Comprehensive test coverage. Estimated Files: 3 new files
Deliverables
| Component | File | Description |
|---|---|---|
| Unit tests | tests/test_sandbox_security.cpp |
Core sandbox tests |
| Integration tests | tests/test_sandbox_integration.cpp |
Full system tests |
| Fuzzer | tests/fuzz_sandbox.cpp |
Random input testing |
Implementation Tasks
-
Write unit tests for all milestones (see individual test criteria).
-
Write integration tests:
- Full app lifecycle
- Permission flow
- Resource cleanup
-
Implement fuzzer:
- Generate random Lua code
- Verify no crashes
- Verify sandbox integrity after each run
-
Security audit checklist (from SANDBOX.md).
Dependencies
- All previous milestones
Milestone 20: Kernel Integration
Goal: Wire sandbox into existing kernel. Estimated Files: Modify existing files
Deliverables
| Component | File | Description |
|---|---|---|
| App lifecycle | src/main/cpp/kernel.cpp |
App start/stop |
| Sandbox manager | src/main/cpp/kernel.cpp |
Multi-app management |
Implementation Tasks
-
Replace global
lua_StatewithLuaSandboxManager:- Create sandbox per app
- Route events to correct sandbox
-
Integrate with RmlUi:
- Bridge RmlUi document events to sandbox
- Replace
Rml::Lua::Interpreterwith sandboxed states
-
Wire up resource cleanup on app stop.
Dependencies
- Milestones 1-18
Summary
| Phase | Milestones | Description |
|---|---|---|
| Foundation | 1-4 | Core sandbox, permissions, logging, paths |
| Core APIs | 5-8 | Timers, JSON, crypto, filesystem, database |
| Network | 9-10 | HTTP and WebSocket |
| Hardware | 11-17 | Camera, mic, audio, location, sensors, BT, contacts |
| System | 18-20 | IPC, testing, integration |
Recommended Order
- Milestone 1 - Must be first (foundation)
- Milestone 2 - Permissions (needed by everything)
- Milestone 3 - Audit/rate limiting (needed by APIs)
- Milestone 4 - Path security (needed by fs/require)
- Milestone 5-6 - Timers, JSON (high value)
- Milestone 7-8 - Storage, database (app data)
- Milestone 9-10 - Network (app connectivity)
- Milestones 11-17 - Hardware (as needed)
- Milestone 18 - IPC (multi-app)
- Milestone 19-20 - Testing & integration
Quick Start
Begin with Milestone 1 to establish the core sandbox. This is the foundation everything else builds on.