1 คะแนน โดย GN⁺ 2024-07-08 | 1 ความคิดเห็น | แชร์ทาง WhatsApp

QuickJS - รัน JavaScript ในแซนด์บ็อกซ์ WebAssembly QuickJS

แพ็กเกจ TypeScript นี้ช่วยให้สามารถรันโค้ด JavaScript ได้อย่างปลอดภัยภายในแซนด์บ็อกซ์ WebAssembly โดยใช้เอนจิน QuickJS เหมาะสำหรับการแยกและรันโค้ดที่ไม่น่าเชื่อถืออย่างปลอดภัย และมอบสภาพแวดล้อมการรันโค้ดที่แข็งแกร่งด้วยการใช้เอนจิน QuickJS ที่มีขนาดเล็กและรวดเร็วซึ่งคอมไพล์เป็น WebAssembly

คุณสมบัติ

  • ความปลอดภัย: สามารถรันโค้ด JavaScript ที่ไม่น่าเชื่อถือได้ในสภาพแวดล้อมที่ปลอดภัยและแยกออกจากกัน
  • ระบบไฟล์: สามารถเมานต์ระบบไฟล์เสมือนได้
  • โมดูล Node แบบกำหนดเอง: สามารถเมานต์โมดูล Node แบบกำหนดเองได้
  • ไคลเอนต์ Fetch: สามารถจัดเตรียมไคลเอนต์ fetch สำหรับเรียก http(s) ได้
  • ตัวรันทดสอบ: รวมตัวรันทดสอบและ expect ที่อิงกับ chai
  • ประสิทธิภาพ: ได้ประโยชน์จากเอนจิน QuickJS ที่มีประสิทธิภาพและน้ำหนักเบา
  • ความยืดหยุ่น: ผสานรวมกับโปรเจ็กต์ TypeScript ที่มีอยู่ได้ง่าย
  • ความเรียบง่าย: มี API ที่ใช้งานง่ายสำหรับการรันและจัดการโค้ด JavaScript ภายในแซนด์บ็อกซ์

ดูเอกสารทั้งหมด

ค้นหาตัวอย่างในรีโพซิทอรี

การใช้งานพื้นฐาน

ต่อไปนี้คือตัวอย่างง่าย ๆ ของการใช้แพ็กเกจ:

import { quickJS } from '@sebastianwessel/quickjs'

// การตั้งค่าทั่วไป เช่น โหลดและเริ่มต้น QuickJS wasm
// เป็นงานที่ใช้ทรัพยากรมาก จึงควรทำเพียงครั้งเดียวถ้าเป็นไปได้
const { createRuntime } = await quickJS()

// สร้างอินสแตนซ์ runtime ทุกครั้งที่รันโค้ด js
const { evalCode } = await createRuntime({
  allowFetch: true, // inject fetch และอนุญาตให้โค้ดดึงข้อมูลได้
  allowFs: true, // เมานต์ระบบไฟล์เสมือนและจัดเตรียมโมดูล 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')) // แสดง "src/dist" ในล็อกของระบบโฮสต์
    console.log(env.MY_ENV_VAR) // แสดง "env var value" ในล็อกของระบบโฮสต์
    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' }

เครดิต

ไลบรารีนี้พัฒนาต่อยอดจาก:

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

เครื่องมือที่ใช้:

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

ใบอนุญาต

โปรเจ็กต์นี้อยู่ภายใต้สัญญาอนุญาต MIT


แพ็กเกจนี้เหมาะอย่างยิ่งสำหรับนักพัฒนาที่ต้องการรันโค้ด JavaScript อย่างปลอดภัยภายในแอปพลิเคชัน TypeScript โดยรับประกันทั้งประสิทธิภาพและความปลอดภัยผ่านแซนด์บ็อกซ์ QuickJS WebAssembly

สรุปโดย GN⁺

บทความนี้อธิบายวิธีรันโค้ด JavaScript อย่างปลอดภัยภายในแซนด์บ็อกซ์ WebAssembly โดยใช้เอนจิน QuickJS ซึ่งมีประโยชน์มากสำหรับการแยกและรันโค้ดที่ไม่น่าเชื่อถือ QuickJS มีจุดเด่นด้านความเบาและความเร็ว พร้อมทั้งผสานรวมกับโปรเจ็กต์ TypeScript ได้อย่างง่ายดาย โปรเจ็กต์ที่มีความสามารถคล้ายกันได้แก่ Deno และ Node.js

1 ความคิดเห็น

 
GN⁺ 2024-07-08
ความคิดเห็นจาก Hacker News
  • ผู้เขียนไลบรารี quickjs-emscripten ชื่นชม standard library ของไลบรารี

    • ถามว่าเคยลองรันบนเบราว์เซอร์หรือบันเดลเลอร์หรือไม่
    • ชี้ให้เห็นปัญหาความเข้ากันได้กับบันเดลเลอร์อย่าง Webpack
    • คำเตือนด้านความปลอดภัย: ไลบรารีเปิดให้ guest code เรียก fetch โดยใช้คุกกี้เดียวกับฟังก์ชัน fetch ของโฮสต์ได้
    • ควรระมัดระวังเมื่อรันโค้ดที่ไม่น่าเชื่อถือ
    • เหตุผลที่ quickjs-emscripten อยู่ในระดับ low-level และหลีกเลี่ยงความสามารถแบบมหัศจรรย์ก็เพื่อรับประกันความปลอดภัย
    • เมื่อรันโค้ดที่ไม่น่าเชื่อถือ ควรตรวจสอบ sandbox และ API อย่างรอบคอบ
    • แนะนำให้อ่านบล็อกโพสต์เกี่ยวกับความปลอดภัยของ sandbox สำหรับปลั๊กอินของ Figma
  • ที่ทำงานก่อนหน้านี้เคยใช้ quickjs-emscripten และพบ "segmentation faults" กับข้อผิดพลาดจำนวนมาก

    • โปรเจ็กต์ถูกยุติไป และถ้าต้องทำใหม่จะใช้ wasm bundle ที่รองรับอย่างเป็นทางการ
  • มีหลายวิธีในการทำ sandbox ให้ JavaScript

    • ถามว่ามีวิธีทำ sandbox สำหรับการเข้าถึง DOM หรือไม่
    • iframes เป็นเทคโนโลยีเดียว แต่ทั้งหนักและช้า
    • กำลังเขียนแอปที่โฮสต์ปลั๊กอิน และหากอนุญาตให้ปลั๊กอินเข้าถึง DOM อาจเกิดปัญหาได้
  • ถามว่าสามารถรันในเบราว์เซอร์ได้หรือไม่

    • หาไม่เจอว่าระบุสภาพแวดล้อมที่รองรับไว้ตรงไหน
  • เคยลองใช้ quickjs แต่สุดท้ายเลือก isolated-vm

    • ทั้งสองไลบรารีตอบโจทย์ด้านความปลอดภัย แต่ isolated-vm ทำได้ดีกว่าในด้านประสิทธิภาพ
  • ผู้เขียนไลบรารี JS sandbox อีกตัวมองว่าแนวทางของ quickjs-emscripten น่าสนใจ

    • กล่าวถึงว่า JS-in-JS หรือ JS-in-WASM ให้การแยกตัวในระดับสูง
    • ชี้ว่า Node.js ไม่ได้ถูกออกแบบมาโดยคำนึงถึง isolation และ sandboxing
    • ถามว่า createRuntime สามารถกำหนดการเรียกไปยังสภาพแวดล้อมโฮสต์อย่างอื่นนอกจาก fetch ได้หรือไม่
    • ระบุว่าการรองรับเบราว์เซอร์น่าจะมีประโยชน์
  • คิดว่าไลบรารีนี้น่าจะใช้รันโค้ด JS ที่ผู้ใช้ส่งมาได้

    • ขอคำแนะนำเกี่ยวกับวิธีรันบันเดลเลอร์ในสภาพแวดล้อม sandbox
  • กล่าวว่าประสิทธิภาพของ QuickJS ไม่อาจแข่งขันกับโฮสต์ JS VM ได้

    • แต่ก็ยังเร็วกว่าอินเทอร์พรีเตอร์ C รุ่นเก่าหรืออินเทอร์พรีเตอร์ที่เขียนด้วย JavaScript
  • เคยทำ high-level wrapper สำหรับ quickjs-emscripten

    • API ของ quickjs-emscripten คล้ายกับ C API ของ quickjs มาก จึงใช้งานยาก
    • การรองรับ require() ทำได้ยาก
    • ใช้วิธี preload ไฟล์โมดูลเข้าไปใน in-memory file system
  • ไลบรารี quickjs-emscripten-sync มีการซิงก์ฟังก์ชันของโฮสต์และ guest แบบอัตโนมัติ ซึ่งอาจกลายเป็นพื้นผิวการโจมตีขนาดใหญ่

    • กังวลเกี่ยวกับความเป็นไปได้ในการหลบหนีออกจาก sandbox
  • ถามว่าเนื่องจากคอมไพล์เป็น wasm แล้ว จึงสามารถรันในเบราว์เซอร์ได้หรือไม่

    • สงสัยว่าสามารถส่งคำขอ fetch โดยไม่แนบคุกกี้ได้หรือไม่