Hacker News new | past | comments | ask | show | jobs | submit login

Interesting approach! As an author of another JS sandbox library[1] that uses workers for isolation plus some JS environment sanitisation techniques, I think that interpreting JS (so, JS-in-JS, or as in this case, JS-in-WASM) gives you the highest level of isolation, and also doesn't directly expose you to bugs in the host JS virtual machine itself. Since you're targeting Node, this is perhaps even more important because (some newer developments notwithstanding) Node.js doesn't really seem to have been designed with isolation and sandboxing in mind (unlike, say, Deno).

From the API, I don't see if `createRuntime` allows you to define calls to the host environment (other than for `fetch`). This would be quite a useful feature, especially because you could use it to restrict communication with the outside world in a controlled way, without it being an all-or-nothing proposition.

Likewise, it doesn't seem to support the browser (at least, running a quick check with esm.sh). I think that that could be a useful feature too.

I'll run some tests as I'm curious what the overhead is in this case, but like I said, this sounds like a pretty solid approach.

[1] @exact-realty/lot




I’m the author of the underlying quickjs-emscripten library. It supports the browser (specifically tested with ESM.sh), as well as Cloudflare Workers, NodeJS, Deno: https://github.com/justjake/quickjs-emscripten?tab=readme-ov...

It has APIs for exposing host functions, calling guest functions, custom module loaders, etc: https://github.com/justjake/quickjs-emscripten?tab=readme-ov...

API docs for newFunction: https://github.com/justjake/quickjs-emscripten/blob/main/doc...


Wow cloudflare workers support is actually super cool. How does it limit memory usage?


The quickjs interpreter C code counts the bytes it's allocated, and refuses to allocate more if over the limit. It decrements by the allocation size when freed. This malloc function is used everywhere the interpreter allocates memory:

    static void *js_def_malloc(JSMallocState *s, size_t size)
    {
        void *ptr;
    
        /* Do not allocate zero bytes: behavior is platform dependent */
        assert(size != 0);
    
        if (unlikely(s->malloc_size + size > s->malloc_limit))
            return NULL;
    
        ptr = malloc(size);
        if (!ptr)
            return NULL;
    
        s->malloc_count++;
        s->malloc_size += js_def_malloc_usable_size(ptr) + MALLOC_OVERHEAD;
        return ptr;
    }




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: