Remix.run Logo
jbpd924 5 hours ago

Interesting!! I've been playing around with QuickJS lately and uses Elixir at work.

I'm interested to hear about your sandboxing approach running untrusted JS code. So you are setting an memory/reduction limit to the process which 100% is a good idea. What other defense-in-depth strategies are you using? possible support for seccomp in the future?

dannote 3 hours ago | parent [-]

Layers right now:

— Memory limits: JS_SetMemoryLimit per-runtime (256 MB default), JS_SetContextMemoryLimit per-context. Exceeding → JS exception, not a crash.

— Execution limits: interrupt handler checks a nanosecond deadline every opcode. For contexts, max_reductions caps JS operations independently of wall-clock time.

— API surface: apis: false gives bare QuickJS — no fetch, no fs, no DOM, no I/O. You control exactly which Elixir functions JS can call via the handlers map. JS cannot call arbitrary Elixir code.

— Conversion limits: max_convert_depth (32) and max_convert_nodes (10k) prevent pathological objects from blowing up during JS↔BEAM conversion.

— Process isolation: separate OS thread, separate QuickJS heap per runtime.

No seccomp — QuickJS runs in-process so seccomp would restrict the entire BEAM. The sandbox boundary is QuickJS-NG's memory-safe interpreter (no JIT, no raw pointer access from JS) plus the API surface control above.