Interface Système WebAssembly (WASI)
[Stable : 1 - Expérimental]
Stable : 1 Stabilité : 1 - Expérimental
Le module node:wasi
ne fournit pas actuellement les propriétés complètes de sécurité du système de fichiers offertes par certains environnements d'exécution WASI. La prise en charge complète du confinement sécurisé du système de fichiers peut ou non être implémentée à l'avenir. Entre-temps, ne vous fiez pas à lui pour exécuter du code non fiable.
Code source : lib/wasi.js
L'API WASI fournit une implémentation de la spécification de l'Interface Système WebAssembly. WASI donne aux applications WebAssembly l'accès au système d'exploitation sous-jacent via une collection de fonctions de type POSIX.
import { readFile } from 'node:fs/promises'
import { WASI } from 'node:wasi'
import { argv, env } from 'node:process'
const wasi = new WASI({
version: 'preview1',
args: argv,
env,
preopens: {
'/local': '/some/real/path/that/wasm/can/access',
},
})
const wasm = await WebAssembly.compile(await readFile(new URL('./demo.wasm', import.meta.url)))
const instance = await WebAssembly.instantiate(wasm, wasi.getImportObject())
wasi.start(instance)
'use strict'
const { readFile } = require('node:fs/promises')
const { WASI } = require('node:wasi')
const { argv, env } = require('node:process')
const { join } = require('node:path')
const wasi = new WASI({
version: 'preview1',
args: argv,
env,
preopens: {
'/local': '/some/real/path/that/wasm/can/access',
},
})
;(async () => {
const wasm = await WebAssembly.compile(await readFile(join(__dirname, 'demo.wasm')))
const instance = await WebAssembly.instantiate(wasm, wasi.getImportObject())
wasi.start(instance)
})()
Pour exécuter l'exemple ci-dessus, créez un nouveau fichier au format texte WebAssembly nommé demo.wat
:
(module
;; Importe la fonction WASI fd_write requise qui écrira les vecteurs io donnés sur stdout
;; La signature de la fonction pour fd_write est :
;; (Descripteur de fichier, *iovs, iovs_len, nwritten) -> Renvoie le nombre d'octets écrits
(import "wasi_snapshot_preview1" "fd_write" (func $fd_write (param i32 i32 i32 i32) (result i32)))
(memory 1)
(export "memory" (memory 0))
;; Écrit 'hello world\n' en mémoire à un décalage de 8 octets
;; Notez la nouvelle ligne de fin qui est requise pour que le texte apparaisse
(data (i32.const 8) "hello world\n")
(func $main (export "_start")
;; Création d'un nouveau vecteur io dans la mémoire linéaire
(i32.store (i32.const 0) (i32.const 8)) ;; iov.iov_base - Il s'agit d'un pointeur vers le début de la chaîne 'hello world\n'
(i32.store (i32.const 4) (i32.const 12)) ;; iov.iov_len - La longueur de la chaîne 'hello world\n'
(call $fd_write
(i32.const 1) ;; file_descriptor - 1 pour stdout
(i32.const 0) ;; *iovs - Le pointeur vers le tableau iov, qui est stocké à l'emplacement mémoire 0
(i32.const 1) ;; iovs_len - Nous imprimons 1 chaîne stockée dans un iov - donc un.
(i32.const 20) ;; nwritten - Un emplacement en mémoire pour stocker le nombre d'octets écrits
)
drop ;; Supprime le nombre d'octets écrits depuis le haut de la pile
)
)
Utilisez wabt pour compiler .wat
en .wasm
wat2wasm demo.wat
Sécurité
[Historique]
Version | Modifications |
---|---|
v21.2.0, v20.11.0 | Clarification des propriétés de sécurité WASI. |
v21.2.0, v20.11.0 | Ajouté dans : v21.2.0, v20.11.0 |
WASI fournit un modèle basé sur les capacités grâce auquel les applications se voient attribuer leurs propres capacités personnalisées : env
, preopens
, stdin
, stdout
, stderr
et exit
.
Le modèle de menace actuel de Node.js ne fournit pas de sandbox sécurisé comme cela est présent dans certains runtimes WASI.
Bien que les fonctionnalités de capacité soient prises en charge, elles ne forment pas un modèle de sécurité dans Node.js. Par exemple, le sandboxage du système de fichiers peut être contourné à l'aide de diverses techniques. Le projet explore la possibilité d'ajouter ces garanties de sécurité à l'avenir.
Classe : WASI
Ajouté dans : v13.3.0, v12.16.0
La classe WASI
fournit l'API d'appel système WASI et des méthodes de commodité supplémentaires pour travailler avec les applications basées sur WASI. Chaque instance WASI
représente un environnement distinct.
new WASI([options])
[Historique]
Version | Modifications |
---|---|
v20.1.0 | valeur par défaut de returnOnExit modifiée en true. |
v20.0.0 | L'option version est désormais obligatoire et n'a pas de valeur par défaut. |
v19.8.0 | champ version ajouté aux options. |
v13.3.0, v12.16.0 | Ajouté dans : v13.3.0, v12.16.0 |
options
<Objet>args
<Tableau> Un tableau de chaînes de caractères que l'application WebAssembly verra comme des arguments de ligne de commande. Le premier argument est le chemin virtuel vers la commande WASI elle-même. Valeur par défaut :[]
.env
<Objet> Un objet similaire àprocess.env
que l'application WebAssembly verra comme son environnement. Valeur par défaut :{}
.preopens
<Objet> Cet objet représente la structure de répertoire locale de l'application WebAssembly. Les clés chaînes depreopens
sont traitées comme des répertoires dans le système de fichiers. Les valeurs correspondantes danspreopens
sont les chemins réels vers ces répertoires sur la machine hôte.returnOnExit
<booléen> Par défaut, lorsque les applications WASI appellent__wasi_proc_exit()
,wasi.start()
renvoie le code de sortie spécifié au lieu de terminer le processus. Le fait de définir cette option surfalse
entraînera la fin du processus Node.js avec le code de sortie spécifié. Valeur par défaut :true
.stdin
<entier> Le descripteur de fichier utilisé comme entrée standard dans l'application WebAssembly. Valeur par défaut :0
.stdout
<entier> Le descripteur de fichier utilisé comme sortie standard dans l'application WebAssembly. Valeur par défaut :1
.stderr
<entier> Le descripteur de fichier utilisé comme erreur standard dans l'application WebAssembly. Valeur par défaut :2
.version
<chaîne de caractères> La version de WASI demandée. Actuellement, les seules versions prises en charge sontunstable
etpreview1
. Cette option est obligatoire.
wasi.getImportObject()
Ajouté dans : v19.8.0
Retourne un objet d'importation qui peut être passé à WebAssembly.instantiate()
si aucune autre importation WASM n'est nécessaire au-delà de celles fournies par WASI.
Si la version unstable
a été passée au constructeur, elle retournera :
{ wasi_unstable: wasi.wasiImport }
Si la version preview1
a été passée au constructeur ou si aucune version n'a été spécifiée, elle retournera :
{ wasi_snapshot_preview1: wasi.wasiImport }
wasi.start(instance)
Ajouté dans : v13.3.0, v12.16.0
instance
<WebAssembly.Instance>
Tente de commencer l'exécution de instance
en tant que commande WASI en invoquant son exportation _start()
. Si instance
ne contient pas d'exportation _start()
, ou si instance
contient une exportation _initialize()
, une exception est levée.
start()
exige que instance
exporte une WebAssembly.Memory
nommée memory
. Si instance
n'a pas d'exportation memory
, une exception est levée.
Si start()
est appelé plus d'une fois, une exception est levée.
wasi.initialize(instance)
Ajouté dans : v14.6.0, v12.19.0
instance
<WebAssembly.Instance>
Tente d'initialiser instance
en tant que réacteur WASI en invoquant son exportation _initialize()
, si elle est présente. Si instance
contient une exportation _start()
, une exception est levée.
initialize()
exige que instance
exporte une WebAssembly.Memory
nommée memory
. Si instance
n'a pas d'exportation memory
, une exception est levée.
Si initialize()
est appelé plus d'une fois, une exception est levée.
wasi.wasiImport
Ajouté dans : v13.3.0, v12.16.0
wasiImport
est un objet qui implémente l'API d'appel système WASI. Cet objet doit être passé en tant qu'importation wasi_snapshot_preview1
lors de l'instantiation d'une WebAssembly.Instance
.