セキュリティモデル
zwasm は、ゲスト(WebAssembly モジュール)とホスト(組み込みアプリケーションまたは CLI)の間に明確な境界を設けています。
信頼境界
+-------------------+ WASI capabilities +------------------+
| Guest (Wasm) | <-- deny-by-default --> | Host (Zig/CLI) |
| | | |
| Linear memory | Imports/exports | Native memory |
| Table entries | <-- validated types --> | Filesystem, env |
| Global variables | | Network, OS APIs |
+-------------------+ +------------------+
正当な Wasm モジュールは、どれほど悪意のあるものであっても、以下のことはできません:
- 自身のリニアメモリ外のホストメモリを読み書きする
- 明示的にインポートされていないホスト関数を呼び出す
- WASI のケーパビリティ制限を回避する
- バリデーション済みの命令ストリーム外のコードを実行する
- トラップを発生させずにコールスタックまたはバリュースタックをオーバーフローさせる
防御レイヤー
モジュールデコード
すべてのバイナリ入力は境界チェックされます。リソース制限により過剰なアロケーションを防止します:
- セクション数: セクションタイプごとに 100〜100,000
- 関数あたりのローカル変数: 最大 50,000(オーバーフロー対策として飽和演算を使用)
- ブロックのネスト深度: 500
- LEB128 の読み取りはバイナリスライスに対して境界チェック済み
バリデーション
コード実行前に Wasm 3.0 の完全な型チェックを行います。62,158 件の spec テストにより正確性を検証しています。
リニアメモリの分離
- すべての load/store は u33 演算(address + offset)を使用し、32 ビットオーバーフローを防止
- ガードページ: 4 GiB + 64 KiB の PROT_NONE 領域により、すべての範囲外アクセスを捕捉
- シグナルハンドラがメモリフォルトを Wasm トラップに変換
JIT セキュリティ
- W^X: コードページはコンパイル中は RW で、実行前に RX に切り替え。書き込み可能と実行可能が同時に有効になることはありません。
- すべての分岐ターゲットはレジスタ IR に対してバリデーション済み
- シグナルハンドラが JIT コード内のフォルトを Wasm トラップに変換
WASI ケーパビリティ
デフォルト拒否モデルで、8 つのケーパビリティフラグがあります:
| フラグ | 制御対象 |
|---|---|
allow-read | ファイルシステムの読み取り |
allow-write | ファイルシステムの書き込み |
allow-env | 環境変数 |
allow-path | パス操作(open, mkdir, unlink) |
allow-clock | クロックアクセス |
allow-random | 乱数生成 |
allow-proc | プロセス操作 |
allow-all | 上記すべて |
46 個の WASI 関数のうち 32 個が実行前にケーパビリティをチェックします。残りの 14 個は安全な操作(args のサイズ照会、fd_close など)です。
ライブラリ API のデフォルト(loadWasi()): cli_default — stdio、clock、random、proc_exit のみ。フルアクセスが必要なエンベッダは loadWasiWithOptions(.{ .caps = .all }) を使用します。
--sandbox モード: すべてのケーパビリティを拒否し、fuel を 10 億命令に設定し、メモリ上限を 256MB に制限します。--allow-* フラグと組み合わせて選択的にアクセスを許可できます:
zwasm untrusted.wasm --sandbox --allow-read --dir ./data
--env KEY=VALUE: 注入された環境変数は、--allow-env がなくてもゲストから常にアクセス可能です。--allow-env フラグはホスト環境のパススルーアクセスを制御します。
スタック保護
- コール深度の制限: 1024(すべての呼び出し時にチェック)
- オペランドスタック: 固定サイズ配列、境界チェック済み
- ラベルスタック: 境界チェック済み
zwasm が保護しないもの
- タイミングサイドチャネル: 定数時間の保証なし
- リソース枯渇: モジュールが無限ループする可能性あり(
--fuelで軽減) - ホスト関数のバグ: ホスト関数に脆弱性がある場合、Wasm コードがそれを引き起こす可能性あり
- Spectre/Meltdown: ハードウェアレベルの軽減策なし
- タイミングによる情報漏洩: JIT コンパイル時間はコード構造によって異なる可能性あり
推奨事項
- 本番環境では
ReleaseSafeでビルド(Zig の境界チェック + オーバーフロー検出) - 信頼できないモジュールには
--fuelを使用して無限ループを防止 --max-memoryでメモリ使用量を制限- モジュールに必要な WASI ケーパビリティのみを付与
- 脆弱性の報告については SECURITY.md を参照