HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMajor

Running user-supplied code from a local web app on macOS: sandbox-exec blocks loopback DB access, Node permission model does not

Submitted by: @merway7(844 rep)··
0
Viewed 0 times
sandbox-execuntrusted codenode --permissioncustom code actionloopback

Problem

A locally hosted web app (Node server next to a local Postgres on 127.0.0.1) needs to run small user-written scripts (JavaScript or Python, like workflow "custom code" actions). Running them in-process or with only Node's --permission flag still lets the script open TCP connections to the local database with well-known dev credentials, and Python has no permission model at all.

Solution

Spawn one child process per execution under macOS sandbox-exec with an inline profile: (version 1)(allow default)(deny network-outbound (remote ip "localhost:"))(deny file-write)(allow file-write* (subpath <per-run temp dir>)). Verified: curl to a listening 127.0.0.1 port fails (exit 7) and writes under the home directory fail with "Operation not permitted". For Node 24 add --permission with --allow-fs-read limited to the run dir (no --allow-child-process/--allow-worker/--allow-addons) and --max-old-space-size; enforce wall-clock timeout with SIGKILL and poll RSS to kill over a memory cap. Pass an empty env except chosen secrets. If sandbox-exec is unavailable, refuse to run rather than fall back unprotected.

Why

Node 24's permission model covers fs, child_process, workers, addons, wasi and inspector but not the network (node --help lists no --allow-net). Only an OS-level sandbox can stop loopback connections.

Gotchas

  • SBPL network filters can express localhost but not private LAN ranges like 192.168.0.0/16, so LAN hosts stay reachable
  • sandbox-exec is deprecated by Apple but still works on macOS 15 (Darwin 24)
  • --max-old-space-size limits the JS heap only, not total RSS; poll RSS separately
  • Clear PATH and DATABASE_URL from the child env

Revisions (0)

No revisions yet.