1 puntos por GN⁺ 2024-07-08 | 1 comentarios | Compartir por WhatsApp

QuickJS - Ejecutar JavaScript en un sandbox de QuickJS con WebAssembly

Este paquete de TypeScript permite ejecutar código JavaScript de forma segura dentro de un sandbox de WebAssembly usando el motor QuickJS. Es ideal para aislar y ejecutar código no confiable de manera segura, y aprovecha el motor QuickJS, ligero y rápido, compilado a WebAssembly para ofrecer un entorno sólido de ejecución de código.

Características

  • Seguridad: permite ejecutar código JavaScript no confiable en un entorno seguro y aislado
  • Sistema de archivos: se puede montar un sistema de archivos virtual
  • Módulos Node personalizados: se pueden montar módulos Node personalizados
  • Cliente Fetch: se puede proporcionar un cliente fetch para realizar llamadas http(s)
  • Test runner: incluye un test runner y expect basado en chai
  • Rendimiento: aprovecha las ventajas del motor QuickJS, ligero y eficiente
  • Versatilidad: se integra fácilmente con proyectos TypeScript existentes
  • Simplicidad: ofrece una API fácil de usar para ejecutar y administrar código JavaScript dentro del sandbox

Ver la documentación completa

Buscar ejemplos en el repositorio

Uso básico

Aquí hay un ejemplo sencillo de uso del paquete:

import { quickJS } from '@sebastianwessel/quickjs'

// Configuración general, como cargar e inicializar QuickJS wasm
// Como es una tarea intensiva en recursos, debería hacerse solo una vez si es posible
const { createRuntime } = await quickJS()

// Se crea una instancia de runtime cada vez que se ejecuta código js
const { evalCode } = await createRuntime({
  allowFetch: true, // inyecta fetch y permite que el código obtenga datos
  allowFs: true, // monta un sistema de archivos virtual y proporciona el módulo node:fs
  env: {
    MY_ENV_VAR: 'env var value'
  },
})

const result = await evalCode(`
  import { join } as path from 'path'
  const fn = async ()=>{
    console.log(join('src','dist')) // registra "src/dist" en el sistema host
    console.log(env.MY_ENV_VAR) // registra "env var value" en el sistema host
    const url = new URL('https://example.com')
    const f = await fetch(url)
    return f.text()
  }
  export default await fn()
`)

console.log(result) // { ok: true, data: '<!doctype html>\n<html>\n[....]</html>\n' }

Créditos

Esta biblioteca se basa en:

  • quickjs-emscripten
  • quickjs-emscripten-sync
  • memfs
  • Chai

Herramientas utilizadas:

  • Bun
  • Biome
  • Hono
  • poolifier-web-worker
  • tshy
  • autocannon

Licencia

Este proyecto está bajo la licencia MIT.


Este paquete es ideal para desarrolladores que buscan ejecutar código JavaScript de forma segura dentro de aplicaciones TypeScript, y garantiza rendimiento y seguridad mediante el sandbox de QuickJS en WebAssembly.

Resumen de GN⁺

Este artículo explica cómo ejecutar código JavaScript de forma segura dentro de un sandbox de WebAssembly usando el motor QuickJS. Esto es muy útil para aislar y ejecutar código no confiable. QuickJS ofrece un rendimiento rápido a la vez que ligero, y tiene la ventaja de integrarse fácilmente con proyectos TypeScript. Proyectos como Deno y Node.js ofrecen funcionalidades similares.

1 comentarios

 
GN⁺ 2024-07-08
Comentarios de Hacker News
  • El autor de la librería quickjs-emscripten elogia la biblioteca estándar de la librería

    • Pregunta si se ha probado en navegadores o bundlers
    • Señala problemas de compatibilidad con bundlers como Webpack
    • Advertencia de seguridad: la librería permite que el código invitado llame a fetch usando las mismas cookies que la función fetch del host
    • Hay que tener cuidado al ejecutar código no confiable
    • La razón por la que quickjs-emscripten es de bajo nivel y evita funciones “mágicas” es para garantizar la seguridad
    • Al ejecutar código no confiable, se debe auditar cuidadosamente el sandbox y la API
    • Recomienda consultar una publicación de blog de Figma sobre la seguridad del sandbox de plugins
  • En un trabajo anterior, experimentó muchos "segmentation faults" y errores al usar quickjs-emscripten

    • El proyecto fue abandonado y, si tuviera que hacerlo de nuevo, usaría el bundle wasm oficialmente soportado
  • Hay varias maneras de hacer sandboxing de JavaScript

    • Pregunta si existe una forma de aislar el acceso al DOM
    • Los iframes son la única tecnología, pero son pesados y lentos
    • Está escribiendo una app que aloja plugins, y permitir a los plugins acceder al DOM podría causar problemas
  • Pregunta si puede ejecutarse en el navegador

    • No puede encontrar ninguna mención sobre los entornos compatibles
  • Había probado quickjs, pero al final eligió isolated-vm

    • Ambas librerías cumplían con los requisitos de seguridad, pero isolated-vm fue superior en rendimiento
  • El autor de otra librería de sandbox para JS considera interesante el enfoque de quickjs-emscripten

    • Menciona que JS-in-JS o JS-in-WASM ofrece un alto nivel de aislamiento
    • Señala que Node.js no fue diseñado pensando en aislamiento y sandboxing
    • Pregunta si createRuntime puede definir llamadas al entorno host además de fetch
    • Menciona que el soporte para navegador sería útil
  • Cree que esta librería permitiría ejecutar código JS proporcionado por usuarios

    • Pide recomendaciones sobre cómo ejecutar un bundler dentro de un entorno sandbox
  • Menciona que el rendimiento de QuickJS no puede competir con el VM de JS del host

    • Es más rápido que intérpretes viejos en C o intérpretes implementados en JavaScript
  • Estaba trabajando en un wrapper de alto nivel para quickjs-emscripten

    • La API de quickjs-emscripten es muy similar a la API en C de quickjs, por lo que es difícil de usar
    • Es difícil implementar soporte para require()
    • Usa un método de precargar archivos de módulos en un sistema de archivos en memoria
  • La librería quickjs-emscripten-sync proporciona sincronización automática entre funciones del host y del invitado, lo que podría representar una gran superficie de ataque

    • Le preocupa la posibilidad de escapar del sandbox
  • Pregunta si puede ejecutarse en el navegador porque fue compilado a wasm

    • Se pregunta si se pueden hacer solicitudes fetch sin adjuntar cookies