1 điểm bởi GN⁺ 2024-07-08 | 1 bình luận | Chia sẻ qua WhatsApp

QuickJS - Chạy JavaScript trong sandbox WebAssembly QuickJS

Gói TypeScript này cho phép chạy mã JavaScript an toàn bên trong sandbox WebAssembly bằng engine QuickJS. Nó phù hợp để cô lập và thực thi mã không đáng tin cậy một cách an toàn, đồng thời cung cấp môi trường thực thi mã vững chắc nhờ tận dụng engine QuickJS nhẹ và nhanh được biên dịch sang WebAssembly.

Tính năng

  • Bảo mật: Có thể chạy mã JavaScript không đáng tin cậy trong môi trường an toàn và được cô lập
  • Hệ thống tệp: Có thể mount hệ thống tệp ảo
  • Module Node tùy chỉnh: Có thể mount các module Node tùy chỉnh
  • Client Fetch: Có thể cung cấp client fetch để thực hiện các lệnh gọi http(s)
  • Test runner: Bao gồm test runner và expect dựa trên chai
  • Hiệu năng: Có thể tận dụng ưu điểm của engine QuickJS nhẹ và hiệu quả
  • Tính linh hoạt: Có thể dễ dàng tích hợp với các dự án TypeScript hiện có
  • Đơn giản: Cung cấp API thân thiện để chạy và quản lý mã JavaScript trong sandbox

Xem toàn bộ tài liệu

Tìm ví dụ trong kho mã

Cách sử dụng cơ bản

Sau đây là một ví dụ đơn giản sử dụng gói này:

import { quickJS } from '@sebastianwessel/quickjs'

// Thiết lập chung như tải và khởi tạo QuickJS wasm
// Vì đây là tác vụ tốn tài nguyên nên nếu có thể chỉ nên thực hiện một lần
const { createRuntime } = await quickJS()

// Tạo một instance runtime mỗi khi chạy mã js
const { evalCode } = await createRuntime({
  allowFetch: true, // tiêm fetch và cho phép mã lấy dữ liệu
  allowFs: true, // mount hệ thống tệp ảo và cung cấp 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')) // ghi log "src/dist" trên hệ thống host
    console.log(env.MY_ENV_VAR) // ghi log "env var value" trên hệ thống 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' }

Ghi công

Thư viện này được xây dựng dựa trên:

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

Công cụ được sử dụng:

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

Giấy phép

Dự án này được phát hành theo giấy phép MIT.


Gói này đặc biệt phù hợp với các nhà phát triển muốn chạy mã JavaScript an toàn bên trong ứng dụng TypeScript, đồng thời đảm bảo hiệu năng và độ an toàn thông qua sandbox WebAssembly QuickJS.

Tóm tắt của GN⁺

Bài viết này giải thích cách sử dụng engine QuickJS để chạy mã JavaScript an toàn trong sandbox WebAssembly. Cách tiếp cận này rất hữu ích để cô lập và thực thi mã không đáng tin cậy. QuickJS mang lại hiệu năng nhanh dù nhẹ, đồng thời có ưu điểm là dễ tích hợp với các dự án TypeScript. Các dự án cung cấp chức năng tương tự bao gồm Deno và Node.js.

1 bình luận

 
GN⁺ 2024-07-08
Ý kiến Hacker News
  • Tác giả của thư viện quickjs-emscripten khen ngợi thư viện chuẩn của thư viện này

    • Hỏi liệu nó đã được chạy trong trình duyệt hoặc bundler hay chưa
    • Chỉ ra vấn đề tương thích với các bundler như Webpack
    • Cảnh báo bảo mật: thư viện cho phép mã khách gọi fetch với cùng cookie như hàm fetch của máy chủ
    • Cần cẩn thận khi chạy mã không đáng tin cậy
    • quickjs-emscripten ở mức thấp và tránh các tính năng “ma thuật” để đảm bảo tính bảo mật
    • Khi chạy mã không đáng tin cậy, cần kiểm tra kỹ sandbox và API
    • Khuyến nghị tham khảo bài đăng blog của Figma về bảo mật sandbox cho plugin
  • Ở công ty trước, đã gặp nhiều "segmentation faults" và lỗi khi dùng quickjs-emscripten

    • Dự án đã bị dừng lại, và nếu làm lại thì sẽ dùng gói wasm được hỗ trợ chính thức
  • Có nhiều cách để sandbox JavaScript

    • Hỏi liệu có cách nào để sandbox quyền truy cập DOM hay không
    • iframe là công nghệ duy nhất nhưng khá nặng và chậm
    • Đang viết một ứng dụng lưu trữ plugin, và nếu cho plugin quyền truy cập DOM thì có thể phát sinh vấn đề
  • Hỏi liệu nó có chạy được trong trình duyệt hay không

    • Không tìm thấy đề cập nào về các môi trường được hỗ trợ
  • Đã dùng thử quickjs nhưng cuối cùng chọn isolated-vm

    • Cả hai thư viện đều đáp ứng yêu cầu bảo mật, nhưng isolated-vm vượt trội hơn về hiệu năng
  • Tác giả của một thư viện sandbox JS khác thấy cách tiếp cận của quickjs-emscripten khá thú vị

    • Nhắc rằng JS-in-JS hoặc JS-in-WASM mang lại mức độ cô lập cao
    • Chỉ ra rằng Node.js không được thiết kế với mục tiêu cô lập và sandboxing
    • Hỏi liệu createRuntime có thể định nghĩa các lời gọi tới môi trường máy chủ ngoài fetch hay không
    • Nói rằng hỗ trợ trình duyệt sẽ rất hữu ích
  • Cho rằng thư viện này có thể dùng để chạy mã JS do người dùng cung cấp

    • Xin gợi ý về cách chạy bundler trong môi trường sandbox
  • Nhắc rằng hiệu năng của QuickJS không thể cạnh tranh với JS VM của máy chủ

    • Nhưng vẫn nhanh hơn các trình thông dịch C cũ hoặc các trình thông dịch được viết bằng JavaScript
  • Đã từng làm một wrapper cấp cao cho quickjs-emscripten

    • API của quickjs-emscripten rất giống C API của quickjs nên khá khó dùng
    • Việc triển khai hỗ trợ require() rất khó
    • Đã dùng cách nạp trước các tệp mô-đun vào hệ thống tệp trong bộ nhớ
  • Thư viện quickjs-emscripten-sync cung cấp đồng bộ tự động giữa hàm máy chủ và hàm khách, điều này có thể tạo ra bề mặt tấn công lớn

    • Lo ngại về khả năng thoát khỏi sandbox
  • Hỏi liệu vì được biên dịch sang wasm nên nó có thể chạy trong trình duyệt hay không

    • Thắc mắc liệu có thể gửi yêu cầu fetch mà không đính kèm cookie hay không