2 months ago
9d74a75A workflow script is model-authored, so it is untrusted input and runs behind
two boundaries that do different jobs:
- a `node:vm` context for AUTHORITY. A fresh realm has no ambient capabilities
and confines the function-constructor chain, so
`[].constructor.constructor("return typeof Bun")()` yields "undefined". This
matters because bash is sandboxed by default (`mode: "workspace-write"`), so an
in-process runner would grant more authority than the tool the model already
has.
- a `Worker` for AVAILABILITY. `vm` cannot interrupt `while(true){}`; without a
separate thread one such script would freeze the whole server. Startup measures
13-16ms against agent calls that take seconds.
The realm is sealed with an allowlist rather than a denylist. A fresh Bun vm
realm ships ShadowRealm, WebAssembly, Atomics, SharedArrayBuffer, WeakRef,
FinalizationRegistry, Intl and eval, and that set grows with each engine release.
Two are not cosmetic: `new ShadowRealm()` inside a vm context panics the Bun
process (exit code 3, which terminate() cannot save you from), and Intl is an
independent clock that would silently poison journal replay.
The worker bootstrap is a string constant on purpose. `Bun.build` with splitting
drops modules referenced only as `new Worker(new URL(...))`, which would ship
broken in the packaged binary alone and never reproduce in development.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kk98XjGKJrKp5ynbiNFMFuParent0f2848e