Security Boundaries

Sandbox Policy

Last updated: 2026-10-15

Macro Handler runs Lua scripts inside a sandboxed runtime. This page documents which APIs are open to scripts, which dangerous constructs are kept closed, and which Android permissions back the runtime calls — all in one place.

1. Forbidden APIs (closed)

The constructs below are closed in the sandbox. A script that uses one of them is rejected before it starts with "Script blocked by security policy" and the reason; a call to a removed function raises a Lua error. Nothing fails silently.

  • Blocked

    loadstring / load / loadfile / dofile

    Turning text into code at run time is disabled: loadstring, load, loadfile, and dofile are removed, and a script that calls them is rejected before it starts. What a shared script does must stay readable before it runs.

  • Blocked

    require / package

    External module loading is blocked. The entire API surface is shipped with the app; no unexpected external code can be injected.

  • Blocked

    io.* / os.execute

    There is no shell, subprocess, or direct file access: the io library (including io.popen) and os.execute are removed. File work goes through the sandboxed File API. This is the core safety guarantee for shared macros.

  • Blocked

    os.exit / os.remove / os.rename / os.tmpname / os.getenv / os.setlocale

    Only the time functions remain in the os library: os.clock, os.date, os.time, and os.difftime.

  • Blocked

    debug.*

    The Lua debug library is fully disabled. A sandboxed script cannot reach host-side state (upvalues, getlocal, sethook).

  • Blocked

    setmetatable / getmetatable

    setmetatable and getmetatable are removed once the app's own helpers have loaded, and a script that calls them is rejected before it starts; the string library is read-only. User scripts cannot install metatables.

  • Blocked

    rawget / rawset / getfenv / setfenv

    Raw table access and environment changes are closed: these functions are removed, and a script that calls them directly or in disguised form is rejected.

  • Blocked

    coroutine.create / wrap / resume / yield

    Creating and running coroutines is closed; only coroutine.status and coroutine.isyieldable remain. Use Async.defer, Async.every, and the promise APIs for timers and waiting.

  • Blocked

    collectgarbage / string.dump

    Controlling the garbage collector and exporting functions as bytecode are closed. A script that calls string.dump is rejected before it starts.

  • Blocked

    luajava / Java.type / Class.forName

    There is no Java bridge or reflection access: luajava is removed, and a script that uses luajava, Java.type, Class.forName, Runtime.getRuntime, or ProcessBuilder is rejected before it starts.

  • Blocked

    // & | ~ << >> (Lua 5.4)

    The Lua 5.4-only floor division (//) and bitwise operators (&, |, ~, <<, >>) are not available. So that scripts behave the same on the LuaJ and native Lua runtimes, a script that uses them is rejected before it starts. Use math.floor(a / b) for floor division; the not-equal comparison (~=) is fine. A // at the start of a line is read as a comment.

  • Blocked

    System.reboot / lockScreen / screenOff / powerDialog

    Commands that reboot the device, lock or turn off the screen, or open the power menu are blocked, including sending lock_screen or power_dialog through System.globalAction, System.pressKey, or System.keyevent. System.openApp, System.closeApp, and System.takeScreenshot are allowed but noted in the runtime log as high-impact actions.

  • Blocked

    Request("http://…")

    Network requests must use HTTPS. A literal http:// address in a script is rejected before the script starts, and any other non-HTTPS request is refused when it is made.

  • Blocked

    Control flow inside inline expressions ({{var}})

    Inline expressions in Visual Builder parameter fields support variable reads + basic math only. ; loadstring require if/while/for and similar are rejected at the block level.

2. Allowed constructs

The public API surface is fully open. The categories below are the most commonly used; see the API documentation for the full 800+ method list.

  • Open

    The entire public API surface

    60 global objects + 800+ methods. Region, Asset, Snap, Touch, Request, JSON, Hud, KV, Async, System, etc.

  • Open

    Error catching with pcall

    The pcall(function() ... end) pattern is fully supported across scripts. Unexpected LuaError values can be caught and logged.

  • Open

    string.* / table.* / math.*

    The pure (side-effect-free) parts of the standard library are open: string.format / string.sub / table.insert / math.floor and so on.

  • Open

    Async.defer / every / promise / await

    A sandboxed timer + promise API: MAX 128 timers + 128 promises. All active timers are auto-cancelled when the script stops.

3. Android permissions backing the runtime

Even though the Lua APIs are open inside the sandbox, several calls depend on Android-side permissions. When a permission is denied, the call returns nil/false or silently no-ops; the script does not crash.

  • Permission

    Display Over Other Apps

    The floating overlay panel, HUD, and runtime overlays require this permission. The macro still runs without it, but on-screen controls cannot be drawn.

  • Permission

    Accessibility Service

    IMAGE / TEXT / COLOR scans, touch simulation, and screen reading depend on this service. If it is disabled, Region:find / quickTap / OCR calls return nil or error out. From version 1.0.51, the layer that receives your taps during optional Teach tap recording and passes them to the app when you lift your finger, the taps of a routine you approved in My Agent Routine, and holding the joystick during Navigation also run through this service; their limits are described in Section 6.2 of the Terms of Service and Section 3.9 of the Privacy Policy.

  • Permission

    MediaProjection (capture only)

    Snap.screenRefresh() uses the MediaProjection token under the hood. The Android 14+ user prompt appears on the first capture; if revoked, the next capture re-prompts.

  • Permission

    Foreground Service (specialUse / mediaProjection)

    The macro runtime and overlay services are declared with Android 14+ Play-compliant foreground service types. The system keeps them alive alongside a visible notification.

  • Permission

    POST_NOTIFICATIONS (Android 13+)

    System.noti() / NOTIFY_TOAST request this permission at runtime. If denied, the call silently no-ops; the macro does not crash.

Lua reference

800+ methods, return types, and example code.

API Documentation

More terminology

Sandbox, pcall, FindParam, mScore, and others.

Glossary