1 pontos por GN⁺ 2024-07-08 | 1 comentários | Compartilhar no WhatsApp

QuickJS - Executando JavaScript em um sandbox QuickJS com WebAssembly

Este pacote TypeScript permite executar código JavaScript com segurança dentro de um sandbox WebAssembly usando o mecanismo QuickJS. É adequado para isolar e executar com segurança código não confiável e oferece um ambiente robusto de execução de código ao aproveitar o mecanismo QuickJS, leve e rápido, compilado para WebAssembly.

Recursos

  • Segurança: permite executar código JavaScript não confiável em um ambiente seguro e isolado
  • Sistema de arquivos: permite montar um sistema de arquivos virtual
  • Módulos Node personalizados: permite montar módulos Node personalizados
  • Cliente Fetch: pode fornecer um cliente fetch capaz de fazer chamadas http(s)
  • Executor de testes: inclui um executor de testes e expect baseado em chai
  • Desempenho: aproveita as vantagens do mecanismo QuickJS, leve e eficiente
  • Versatilidade: integra-se facilmente a projetos TypeScript existentes
  • Simplicidade: fornece uma API amigável para executar e gerenciar código JavaScript dentro do sandbox

Ver documentação completa

Encontrar exemplos no repositório

Uso básico

A seguir, um exemplo simples de uso do pacote:

import { quickJS } from '@sebastianwessel/quickjs'

// Configuração geral, como carregar e inicializar o wasm do QuickJS
// Como é uma tarefa intensiva em recursos, deve ser feita apenas uma vez, se possível
const { createRuntime } = await quickJS()

// Cria uma instância de runtime sempre que o código JS for executado
const { evalCode } = await createRuntime({
  allowFetch: true, // injeta fetch e permite que o código busque dados
  allowFs: true, // monta um sistema de arquivos virtual e fornece o 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" no sistema do host
    console.log(env.MY_ENV_VAR) // registra "env var value" no sistema do 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 é baseada em:

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

Ferramentas utilizadas:

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

Licença

Este projeto está sob a licença MIT.


Este pacote é ideal para desenvolvedores que desejam executar código JavaScript com segurança dentro de aplicações TypeScript, garantindo desempenho e segurança por meio do sandbox QuickJS em WebAssembly.

Resumo do GN⁺

Este artigo explica como executar código JavaScript com segurança dentro de um sandbox WebAssembly usando o mecanismo QuickJS. Isso é muito útil para isolar e executar código não confiável. O QuickJS oferece desempenho rápido apesar de ser leve, além da vantagem de se integrar facilmente a projetos TypeScript. Projetos como Deno e Node.js oferecem funcionalidades semelhantes.

1 comentários

 
GN⁺ 2024-07-08
Comentários do Hacker News
  • o autor da biblioteca quickjs-emscripten elogia a biblioteca padrão da biblioteca

    • pergunta se ela já foi executada no navegador ou com um bundler
    • aponta problemas de compatibilidade com bundlers como o Webpack
    • alerta de segurança: a biblioteca permite que o código convidado chame fetch usando os mesmos cookies da função fetch do host
    • é preciso ter cuidado ao executar código não confiável
    • o motivo de quickjs-emscripten ser de baixo nível e evitar recursos “mágicos” é garantir segurança
    • ao executar código não confiável, é preciso auditar cuidadosamente o sandbox e a API
    • recomenda consultar a postagem de blog da Figma sobre a segurança do sandbox de plugins
  • em um emprego anterior, usou quickjs-emscripten e enfrentou muitos "segmentation faults" e erros

    • o projeto foi interrompido e, se fosse refazer, usaria um bundle wasm com suporte oficial
  • existem várias formas de fazer sandbox de JavaScript

    • pergunta se há alguma forma de isolar o acesso ao DOM
    • iframes são a única tecnologia, mas são pesados e lentos
    • está escrevendo um app que hospeda plugins, e permitir acesso ao DOM para plugins pode causar problemas
  • pergunta se é possível executar no navegador

    • não consegue encontrar menção aos ambientes suportados
  • já usou quickjs, mas no fim escolheu isolated-vm

    • ambas as bibliotecas atenderam aos requisitos de segurança, mas isolated-vm teve desempenho superior
  • o autor de outra biblioteca de sandbox para JS acha a abordagem do quickjs-emscripten interessante

    • menciona que JS-in-JS ou JS-in-WASM oferece um alto nível de isolamento
    • aponta que o Node.js não foi projetado pensando em isolamento e sandboxing
    • pergunta se createRuntime permite definir chamadas ao ambiente do host além de fetch
    • comenta que suporte a navegador seria útil
  • acha que esta biblioteca permitiria executar código JS fornecido pelo usuário

    • pede recomendações sobre como executar um bundler em um ambiente sandbox
  • menciona que o desempenho do QuickJS não pode competir com a VM JS do host

    • é mais rápido do que interpretadores antigos em C ou interpretadores implementados em JavaScript
  • estava trabalhando em um wrapper de alto nível para quickjs-emscripten

    • a API de quickjs-emscripten é muito parecida com a API C do quickjs, o que a torna difícil de usar
    • foi difícil implementar suporte a require()
    • usou uma abordagem de pré-carregar arquivos de módulo em um sistema de arquivos em memória
  • a biblioteca quickjs-emscripten-sync fornece sincronização automática entre funções do host e do convidado, o que pode representar uma grande superfície de ataque

    • manifesta preocupação com a possibilidade de escapar do sandbox
  • pergunta se, por ter sido compilado para wasm, é possível executá-lo no navegador

    • quer saber se é possível fazer requisições fetch sem anexar cookies