npm installを実行すると、パッケージをダウンロードするだけでなく、パッケージが用意したスクリプトも動くことがあります。そのコードを普段の開発環境で動かせば、実行するユーザーが読めるファイルや、プロセスへ渡した環境変数に触れられます。

Izanagiは、こうした開発用コマンドをサンドボックス内で実行し、ファイルアクセスやネットワーク通信、子プロセスの起動を記録するRust製のツールです。作業場所を隔離する機能に加え、実行したコードが何をしようとしたかを調べる機能を持っています。

最初の記事では、Izanagiで何ができるかを説明します。対象は2026年10月8日に確認したmainのbc74c86eです。READMEだけでなく、コマンド実装、検知ルール、関連PRと検証記録を参照しています。

コマンドを別の作業環境で動かす

基本の操作は、設定を作り、サンドボックス内でコマンドを実行することです。

izanagi init
izanagi exec -- npm install

initは対話形式で設定を生成します。バックエンドや共有するディレクトリを選び、execへ実行したいコマンドを渡します。サンドボックスの環境には、使うビルドツールやランタイムを用意しておく必要があります。

execの実装は、稼働中のセッションがあればそこへ接続し、なければ単発の実行環境を起動します。標準出力、標準エラー、終了コードを呼び出し元へ返し、単発実行の終了後は停止処理を行います。

環境を起動したまま、複数の作業を続けることもできます。

# このターミナルで起動したまま待機する
izanagi up
# 別のターミナルから操作する
izanagi exec -- npm test
izanagi shell
izanagi down

shellは対話シェルです。PTYを使い、入力、出力、端末サイズの変更を扱います。upで起動した環境は、Ctrl+Cまたはdownで停止します。

設定は作業ディレクトリから求めたハッシュごとに保存されるので、プロジェクト単位で共有範囲や監視条件を分けられます。

隔離の方法を選ぶ

サンドボックスのバックエンドには、Apple Container、QEMU、LinuxのLandlockがあります。nativeという指定の意味はOSによって変わります。バックエンドを選択するコードでは、macOSならApple Container、LinuxならLandlockを選びます。

バックエンド実行環境主な隔離の方法
Apple ContainermacOSコンテナ用の仮想化環境で実行
QEMUmacOS・LinuxゲストOSを起動してVM内で実行
LandlockLinuxホスト上の子プロセスへファイルアクセス制限を適用

QEMUとコンテナでは、ホストから共有したディレクトリをゲストの作業場所へ渡します。LinuxのLandlockは別のOSを起動せず、ホストのパスに対してアクセスルールを設定します。Landlockの実装は、共有対象の読み書きと、実行に必要なシステムファイルの読み取りなどを許可しています。

共有した場所は、実行するコードが作業する場所でもあります。プロジェクトを読み書き可能で渡せば、そのプロジェクトのファイルを書き換えられます。ホストの秘密鍵を共有しないことと、共有したソースコードを変更できないことは別の条件です。

LinuxでLandlockとeBPFを使う場合は、対応機能を含めてビルドします。

cargo build --release --features landlock,ebpf

Linux側の必要機能がないビルドでは、再ビルド方法を示すエラーになります。PR #6では、この案内とLandlockによるシステムコマンドの実行、終了時の後片付けを修正しています。

ファイルや通信へのアクセスを記録する

隔離と監視は、それぞれ別の部品です。Sandboxが実行環境を管理し、TracerがOSへの操作をイベントとして集め、Detectorがルールと照合します。

flowchart LR
    C[開発用コマンド] --> S[Sandboxで実行]
    S --> T[Tracerが操作を収集]
    T --> D[Detectorがルールと照合]
    D --> L[ログとアラート]

syscallは、プロセスがOSにファイルを開く、接続する、別のプログラムを起動するといった操作を依頼する入口です。IzanagiはLinuxのeBPFやmacOSのDTraceを使い、こうした操作を監視します。QEMUでは、ゲスト内のagentからイベントをホストへ送るvm-agentを使えます。

izanagi up --sandbox=qemu --tracer=vm-agent

バックエンドとTracerの組み合わせは確認が必要です。現行のselect_tracerでは、vm-agentを明示指定できるのはQEMUです。また、明示的に選んだQEMU・Apple Containerでautoを使うと、監視を行わないNullTracerになります。隔離環境を起動したことだけで、内部のsyscallも収集しているとは判断できません。

記録したイベントは、CLIから閲覧できます。

izanagi logs
izanagi logs --suspicious
izanagi logs --follow

--suspiciousは不審な操作に絞り、--followは追加されるログを追います。たとえば、依存関係のインストール中に、通常のキャッシュへの書き込みと、秘密鍵へのアクセスが混ざっていないかを調べるために使えます。

検知できる操作

組み込みの検知ルールには、機密ファイルへのアクセス、許可リスト外への通信、不審なコマンドの実行、プロセスのベースラインから外れた実行、環境変数ファイルへのアクセスがあります。

SuspiciousPathRuleは、設定したパスのパターンとアクセスを照合します。SSH鍵やクラウドの認証情報を置くディレクトリなどが対象になります。

NetworkAllowlistRuleは、connectやsendtoの宛先IPを許可リストと比較します。ドメイン名を指定した場合は、名前解決したIPを使います。許可リストが空なら、通信全体を警告対象にします。

このルールはアラートを作る処理です。警告が出たというだけで、接続そのものを拒否したわけではありません。DNSやHTTPSの通信制御は、後述するプロキシ側の機能です。

UnexpectedExecRuleは、curl、wget、ncなどのコマンド名を検知します。これらは通常の開発作業でも使うので、検知しただけで攻撃と断定する情報ではありません。どの処理から起動されたか、通信先やファイルアクセスと合わせて確認するための手掛かりです。

EnvAccessRuleは、/proc/self/environや/proc/<pid>/environへのファイル操作を検知します。すでにプロセスのメモリにある環境変数を、JavaScriptのprocess.envで読む操作まで、すべてsyscallとして観測できるわけではありません。

そのため、何を渡すかも実行環境側で管理します。CLIのbuild_sandbox_envが組み立てる環境変数は、固定のPATHと、存在する場合のTERMです。ホストの環境変数を全部コピーする処理にはなっていません。実際の環境は、この引数に加えて、選んだイメージやバックエンドの設定にも依存します。

DNSとHTTPSをプロキシで扱う

Izanagiには、DNSプロキシとHTTP・HTTPSのキャプチャ用プロキシもあります。ProxyManagerは、izanagi upの設定に応じてこれらを子プロセスとして起動します。

DNSプロキシは、許可したドメインの問い合わせを上流へ送り、許可リスト外にはダミーのIPを返します。これは、そのDNSプロキシを通る名前解決に対する制御です。IPを直接指定する通信なども含めた、ネットワーク全体の遮断と同じではありません。

HTTPキャプチャは、リクエストの内容を記録して403を返します。HTTPS側は、専用CAで接続先の証明書を生成するTLS MITM方式です。クライアントがそのCAを信頼し、通信をプロキシへ届ける構成で、暗号化される前後のリクエストを扱います。

izanagi-http-captureは、許可したホストへのHTTPSリクエストを上流へ転送し、それ以外を拒否します。証明書の固定検証を行うクライアントなど、通常のCA信頼設定だけでは通らない通信もあります。

このプロキシには、シークレット置換もあります。サンドボックス内ではダミーのトークンを使い、許可した上流へ転送するときに本物へ置き換えます。

サンドボックス内: ダミーのトークンを使ってリクエストを作る
  → プロキシ: 宛先を確認し、ダミー値を本物へ置換する
  → 許可された上流: 本物のトークンでリクエストを受け取る

本物のトークンを、依存パッケージの動くプロセスへ直接渡さずにリクエストを送るための機能です。現行のSecretMapは文字列を置換する実装なので、対応するHTTP通信をプロキシへ通す構成が必要です。任意のプログラムの認証情報を自動で代替するものではありません。

なお、Apple Containerの設定でnetwork = "none"を指定する構成は、現在の設定検証では未サポートとして拒否されます。DNSの制御やプロキシ転送と、ネットワークの完全遮断は区別して設定します。

AIエージェントから実行する

izanagi mcpで、stdioのMCPサーバーとして起動できます。提供するツールは次の三つです。

ツール操作
sandbox_statusセッションの稼働状態を確認
sandbox_execコマンドと引数を指定して実行
sandbox_shell文字列を/bin/sh -cへ渡して実行

MCPのハンドラーは、稼働中のセッションを確認してから実行します。サーバーを起動するだけでサンドボックスも作るわけではなく、先にizanagi upで環境を用意します。

MCPのsandbox_shellは、一つのシェルコマンドを実行するAPIです。CLIのizanagi shellが提供する、キーボード入力を送り続ける対話シェルとは用途が異なります。

このMCPツールを使えば、AIエージェントが依存関係のインストールやテストを行う際の実行先をIzanagiのセッションにできます。エージェントがほかの実行ツールを使う場合まで、自動的にIzanagiへ転送する仕組みではありません。

監視が止まった場合

監視を前提にコマンドを実行するなら、監視の起動に失敗した状態で作業を始めないことも必要です。

Issue #30では、VM agentの認証や監視の初期化が失敗しても、ホスト側で起動成功になってしまう問題が報告されました。PR #34では、agentからTraceStartedという応答を受け取るまで監視開始とせず、失敗時には起動したサンドボックスを停止するよう修正しています。

監視有効のEngineでは、実行中に必要なイベントストリームが失敗した場合も、処理を中断して呼び出し元へ伝えます。--tracer=noneは、監視を明示的に外す設定です。この方針とホスト・agentの更新条件は、プロトコル文書に記されています。

ホストとagentの通信は、現在はバージョン付きのpostcard形式とHMAC-SHA256を使います。READMEに残るbincodeの記述からは変更されており、PR #29で移行しています。さらに監視開始の応答も追加されているため、ホストだけ更新して古いゲストイメージを使い続ける構成は避け、同じリビジョンで揃えてビルドします。

現在の確認範囲

最新mainのCIは成功しています。PR #36にはLinuxホスト458件、macOSホスト480件、Linux agent38件のテスト成功が記録されています。通信を途中まで受信したところで入力や端末リサイズが発生するケースも、回帰テストに含まれています。

一方、10月8日の挙動確認記録では、既存のQEMUイメージがHello前に接続を閉じ、スモークテストが失敗しています。最新agentとeBPFを組み込んだイメージでのExec・Event・Shellの成功確認は、残作業として明記されています。PR #29での実VM成功記録と、それ以降の修正を含む最新イメージの確認は分けて読む必要があります。

WindowsのAppContainerとETWは、READMEでは将来の対応として挙げられています。今回確認した実装の対象はmacOSとLinuxです。この記事のためにVMやコンテナを起動して、これらの検証を再実行したわけではありません。

Izanagiの操作を組み立てる際は、まず実行環境と共有範囲を決め、そこで使えるTracerを選びます。次に検知したいパスや通信先を設定し、通信を制御する場合はプロキシを通す経路を用意します。隔離、操作の記録、ルールによる検知、プロキシによる転送制御が、それぞれどこを担当するかを確認して使う構成です。