1 points par GN⁺ 2024-07-08 | 1 commentaires | Partager sur WhatsApp

QuickJS - Exécuter JavaScript dans un sandbox QuickJS WebAssembly

Ce package TypeScript permet d’exécuter du code JavaScript en toute sécurité dans un sandbox WebAssembly à l’aide du moteur QuickJS. Il convient particulièrement à l’isolation et à l’exécution sécurisées de code non fiable, et fournit un environnement d’exécution robuste grâce au moteur QuickJS, léger et rapide, compilé en WebAssembly.

Fonctionnalités

  • Sécurité : permet d’exécuter du code JavaScript non fiable dans un environnement sûr et isolé
  • Système de fichiers : permet de monter un système de fichiers virtuel
  • Modules Node personnalisés : permet de monter des modules Node personnalisés
  • Client Fetch : permet de fournir un client fetch capable d’effectuer des appels http(s)
  • Test runner : inclut un test runner ainsi que expect basé sur chai
  • Performance : permet de bénéficier des avantages du moteur QuickJS, léger et efficace
  • Polyvalence : s’intègre facilement dans des projets TypeScript existants
  • Simplicité : fournit une API conviviale pour exécuter et gérer du code JavaScript dans le sandbox

Voir la documentation complète

Trouver des exemples dans le dépôt

Utilisation de base

Voici un exemple simple d’utilisation du package :

import { quickJS } from '@sebastianwessel/quickjs'

// Configuration générale, comme le chargement et l'initialisation de QuickJS wasm
// Comme il s'agit d'une opération gourmande en ressources, il faut si possible ne l'effectuer qu'une seule fois
const { createRuntime } = await quickJS()

// Une instance de runtime est créée à chaque exécution de code js
const { evalCode } = await createRuntime({
  allowFetch: true, // injecte fetch et autorise le code à récupérer des données
  allowFs: true, // monte un système de fichiers virtuel et fournit le module 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')) // affiche "src/dist" dans les logs sur le système hôte
    console.log(env.MY_ENV_VAR) // affiche "env var value" dans les logs sur le système hôte
    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édits

Cette bibliothèque s’appuie sur :

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

Outils utilisés :

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

Licence

Ce projet est distribué sous licence MIT.


Ce package est idéal pour les développeurs qui veulent exécuter du code JavaScript en toute sécurité dans des applications TypeScript, tout en garantissant performances et sûreté grâce au sandbox QuickJS WebAssembly.

Résumé de GN⁺

Cet article explique comment exécuter du code JavaScript en toute sécurité dans un sandbox WebAssembly à l’aide du moteur QuickJS. C’est particulièrement utile pour isoler et exécuter du code non fiable. QuickJS offre des performances rapides tout en restant léger, avec l’avantage de pouvoir être facilement intégré dans des projets TypeScript. Parmi les projets offrant des fonctionnalités similaires, on peut citer Deno et Node.js.

1 commentaires

 
GN⁺ 2024-07-08
Avis Hacker News
  • L’auteur de la bibliothèque quickjs-emscripten fait l’éloge de la bibliothèque standard de la bibliothèque

    • Demande si elle a été testée dans un navigateur ou avec un bundler
    • Signale des problèmes de compatibilité avec des bundlers comme Webpack
    • Avertissement de sécurité : la bibliothèque permet au code invité d’appeler fetch en utilisant les mêmes cookies que la fonction fetch de l’hôte
    • Il faut être prudent lors de l’exécution de code non fiable
    • La raison pour laquelle quickjs-emscripten est bas niveau et évite les fonctionnalités magiques est de garantir la sécurité
    • Lors de l’exécution de code non fiable, il faut auditer soigneusement le sandbox et les API
    • Recommande de consulter un billet de blog sur la sécurité du sandbox des plugins de Figma
  • Dans un emploi précédent, il a rencontré de nombreuses « segmentation faults » et erreurs en utilisant quickjs-emscripten

    • Le projet a été abandonné et, s’il devait recommencer, il utiliserait les bundles wasm officiellement pris en charge
  • Il existe plusieurs façons de sandboxer JavaScript

    • Demande s’il existe un moyen de sandboxer l’accès au DOM
    • Les iframes sont la seule technologie, mais elles sont lourdes et lentes
    • Il développe une application qui héberge des plugins, et autoriser les plugins à accéder au DOM pourrait poser problème
  • Demande si cela peut s’exécuter dans le navigateur

    • Ne trouve aucune mention des environnements pris en charge
  • Il a essayé quickjs mais a finalement choisi isolated-vm

    • Les deux bibliothèques satisfaisaient les exigences de sécurité, mais isolated-vm était meilleur en termes de performances
  • L’auteur d’une autre bibliothèque de sandbox JS trouve l’approche de quickjs-emscripten intéressante

    • Mentionne que JS-in-JS ou JS-in-WASM offre un haut niveau d’isolation
    • Souligne que Node.js n’a pas été conçu en pensant à l’isolation et au sandboxing
    • Demande si createRuntime peut définir des appels vers l’environnement hôte autres que fetch
    • Mentionne qu’une prise en charge du navigateur serait utile
  • Pense que cette bibliothèque permettrait d’exécuter du code JS fourni par l’utilisateur

    • Demande des recommandations sur la façon d’exécuter un bundler dans un environnement sandboxé
  • Mentionne que les performances de QuickJS ne peuvent pas rivaliser avec celles de la VM JS hôte

    • C’est plus rapide qu’un ancien interpréteur C ou qu’un interpréteur implémenté en JavaScript
  • Il travaillait sur un wrapper de haut niveau pour quickjs-emscripten

    • L’API de quickjs-emscripten est très similaire à l’API C de quickjs, ce qui la rend difficile à utiliser
    • L’implémentation de la prise en charge de require() est difficile
    • Utilise une méthode consistant à précharger les fichiers de module dans un système de fichiers en mémoire
  • La bibliothèque quickjs-emscripten-sync fournit une synchronisation automatique entre les fonctions hôte et invité, ce qui peut constituer une grande surface d’attaque

    • S’inquiète de la possibilité de s’échapper du sandbox
  • Demande si, puisqu’elle a été compilée en wasm, elle peut s’exécuter dans le navigateur

    • Se demande s’il est possible d’effectuer des requêtes fetch sans joindre les cookies