エグゼクティブサマリー
| 属性 | 詳細 |
|---|---|
| ツール | Azazel |
| テクノロジー | eBPF (CO-RE、BTFベース) |
| 対象 | Dockerコンテナ/汎用コンテナで実行しているOpenClaw Gatewayエージェント |
| フックポイント | 19(トレースポイント + kprobe) |
| 出力 | NDJSON、Elasticsearch/Splunk/jqに対応 |
重要なポイント:自律ループで動作しているAIエージェントは、プロンプトが示唆するよりも大幅に多くのシステムコールを実行します。アプリケーションレベルのログでは、エージェントが報告していることではなく、オペレーティングシステムレベルで実際に行っていることが明らかになります。Azazelはカーネルレベルの可視性を提供します。エージェントのコンテナ内で実行されるすべてのプロセス実行、ファイルアクセス、ネットワーク接続、セキュリティ関連イベントをエージェントが無効化、変更、検出できないeBPFトレースポイントを使用して可視化します。
OpenClawエージェントセッションのトレースからの主な発見:
- 単純な「ディスク容量確認」プロンプトが47個の
process_execイベント、312個のfile_openイベント、および8個のnet_connectイベントを生成しました。アプリケーションログは単一のツール呼び出しを報告していました - エージェントはAPIキー、セッション履歴、チャネルトークンを含む構成ファイルへのアクセスを定期的に行っています
- プロセスツリーはアプリケーションレベルの可視性では見えない隠れたサブプロセスチェーンを明らかにします
1. 問題
1.1 エージェント信頼ギャップ
OpenClawは、独自のデバイスで実行されるAIエージェントプラットフォームです。エージェントはDockerコンテナ内で以下へのアクセス権を持って動作します:
- 完全なLinuxシェル(
exec、bash、任意のコマンド) - アウトバウンドネットワーク接続(HTTP、DNS、任意のTCP/UDP)
- 永続ファイルシステム(設定、認証情報、セッション履歴)
- 接続されたチャネル(WhatsApp、Telegram、Slack、Discord、iMessage)
エージェントは自律ループで実行され、メッセージを受け取り、推論し、ツールを実行し、応答します。多くの場合、個別のアクションについて人間によるレビューなしに行われます。1つのプロンプトと次のプロンプトの間に、エージェントは数十のシェルコマンドを実行し、ネットワーク接続を開き、ファイルを読み書きし、外部ツールを呼び出す可能性があります。
質問は簡単です:エージェントは実際に何をしているのか?
アプリケーションレベルのログはエージェントが報告することだけをキャプチャしており、実際に実行することはキャプチャしません。これはマルウェア分析で直面する同じ基本的な問題です:対象がそれ自体のログを制御する場合、ログは無価値です。
Azazelはマルウェアサンドボックスで使用されるのと同じ原則を適用します:対象が見ることができない、到達できない、または干渉できないレイヤーから観察します。eBPFトレースポイントはカーネル空間で実行され、エージェントのアドレス空間の外にあり、プロセスリストに見えず、それが呼び出すシステムコールによって検出できません。発見するファイルはなく、検出するプロセスはなく、プローブするソケットもありません。
エージェントは監視されていることを知りません。正にそうだからこそ、本当の動作意図を明かしながら、本来通りに動作します。/etc/shadowを読み取り、リバースシェルを開き、またはセッションデータを流出させるエージェントは、その視点からは誰も見ていないため、回避を試みることなく、そうします。
これがコアの利点です:気づいていない対象はその動作を適応させることができません。あなたが観察するのはエージェントが本当にしていることであって、見せたいことではありません。
1.2 何が悪くなる可能性があるか
これらは仮説的なシナリオではありません。自律ループで動作しているエージェントを使用:
| シナリオ | 根本原因 | 観察可能な動作 |
|---|---|---|
| 認証情報流出 | エージェントはAPIキーを含む構成ファイルを読み取り、ネットワーク上に送信する | 機密パスのfile_open + 未知のIPへのnet_connect |
| 予期しないコード実行 | エージェントはインターネットからスクリプトをダウンロードして実行する | net_connect → /tmp/へのfile_write → /tmp/からのprocess_exec |
| リソース枯渇 | エージェントはフォークループに入るか、制限されないプロセスを生成する | 急速なprocess_cloneイベント、PID数上昇 |
| チャネル経由のプロンプト注入 | 悪意のあるメッセージがツール実行をトリガーする | 予期しないバイナリのprocess_exec(curl、wget、nc) |
| データ流出 | エージェントはセッション履歴を読み取り、外部エンドポイントに送信する | *.jsonlセッションファイルのfile_read + アウトバウンドnet_connect |
アプリケーションレベルの監視はエージェント自体のログを制御するため、これらの動作を確実に検出することはできません。
2. eBPFを使用する理由
2.1 カーネルレベルの可視性
eBPF(拡張Berkeley Packet Filter)を使用すると、プログラムをカーネルトレースポイントとkprobeに直接接続できます。これはエージェント監視に不可欠ないくつかのプロパティを提供します:
回避不可能:エージェントはトレーサーを無効化、変更、または検出できません。eBPFプログラムはカーネル空間で実行されます。監視対象のプロセスはそれらに干渉するメカニズムを持っていません。
ゼロランタイム依存:Azazelは単一の静的Goバイナリにコンパイルされます。エージェント、デーモン、コンテナ内にインストールするライブラリはありません。
無視できるオーバーヘッド:eBPFプログラムはサンドボックス化されたVMで実行され、実行時間は制限されています。トレースされたコンテナへのパフォーマンス影響は最小限です。
コンテナ対応:Cgroupベースのフィルタリングにより、ホストまたは他のコンテナからのノイズをキャプチャせずに、特定のコンテナをトレースできます。
CO-RE(Compile Once, Run Everywhere):BTFとvmlinux.hを使用して、コンパイルされたeBPFプログラムは再コンパイルなしでカーネルバージョン間で動作します。
2.2 Azazelがキャプチャするもの
Azazelは4つのカテゴリ全体にわたって19個のフックポイントを接続します:
| カテゴリ | イベント | 詳細 |
|---|---|---|
| プロセス | process_exec、process_exit、process_clone |
完全なプロセスツリー:ファイル名、argv、終了コード、クローンフラグ、親PID |
| ファイル | file_open、file_write、file_read、file_unlink、file_rename |
パス名、フラグ、バイト数 |
| ネットワーク | net_connect、net_bind、net_listen、net_accept、net_sendto、net_dns |
IPv4/IPv6アドレス、ポート、udp_sendmsgのkprobe経由のDNS検出 |
| セキュリティ | mmap_exec、ptrace、module_load |
W+Xメモリマッピング、プロセスインジェクション試行、カーネルモジュール読み込み |
すべてのイベントに含まれるもの:タイムスタンプ、PID、TGID、PPID、UID、GID、comm、cgroupID、およびコンテナID。これにより、特定のコンテナ内の特定のプロセスに対するすべてのアクションの完全な帰属が提供されます。
3.1 セットアップ
OpenClawコンテナをターゲットにしてAzazelを開始するか、Azazelを使用したdev-containerを使用してください。詳細は次を参照してください:Azazel Github
# OpenClawコンテナを特定する
sudo ./bin/azazel list-containers
# トレースを開始する
sudo ./bin/azazel --container <openclaw_container_id> --output events.json --pretty
Azazelはcgroupでイベントをフィルタリングし、指定されたコンテナからのアクティビティのみをキャプチャします。すべてのイベントはNDJSON、行ごとに1つのJSONオブジェクトとして書き込まれます。
3.2 観察されたエージェント動作
「システムの健全性を確認し、不足している依存関係をインストール」するよう指示されたOpenClawセッションの標準中に、次のプロセスツリーがキャプチャされました:
{
"timestamp": "2026-02-10T10:15:03.112Z",
"event_type": "process_exec",
"pid": 8421,
"ppid": 8400,
"uid": 0,
"comm": "bash",
"container_id": "a1b2c3d4e5f6",
"filename": "/bin/bash",
"args": "/bin/bash -c apt-get update && apt-get install -y python3-pip"
}
{
"timestamp": "2026-02-10T10:15:07.334Z",
"event_type": "process_exec",
"pid": 8445,
"ppid": 8421,
"uid": 0,
"comm": "apt-get",
"container_id": "a1b2c3d4e5f6",
"filename": "/usr/bin/apt-get",
"args": "apt-get install -y python3-pip"
}
エージェントはコンテナ内でrootとしてapt-getを実行しました。これはこの特定のプロンプトの場合の予想される動作ですが、カーネルレベルのトレースなしに、エージェントが求められたことだけをしたことを検証する方法はありません。
3.3 ネットワークアクティビティ
同じセッションで、アウトバウンドネットワーク接続が生成されました:
{
"timestamp": "2026-02-10T10:15:04.201Z",
"event_type": "net_connect",
"pid": 8421,
"comm": "curl",
"container_id": "a1b2c3d4e5f6",
"sa_family": "AF_INET",
"dst_addr": "104.18.32.7",
"dst_port": 443
}
{
"timestamp": "2026-02-10T10:15:08.892Z",
"event_type": "net_dns",
"pid": 8445,
"comm": "apt-get",
"container_id": "a1b2c3d4e5f6",
"sa_family": "AF_INET",
"dst_addr": "8.8.8.8",
"dst_port": 53
}
DNS解決とパッケージリポジトリへのHTTPS接続はapt-getの場合は予想されます。暗号通貨マイニングプール、ファイル共有サービス、または未知のIPへの予期しない宛先への接続は、トレースで即座に表示されます。
3.4 ファイルシステムアクティビティ
{
"timestamp": "2026-02-10T10:15:12.445Z",
"event_type": "file_open",
"pid": 8421,
"comm": "bash",
"container_id": "a1b2c3d4e5f6",
"filename": "/root/.openclaw/config.yaml"
}
{
"timestamp": "2026-02-10T10:15:12.891Z",
"event_type": "file_read",
"pid": 8421,
"comm": "cat",
"container_id": "a1b2c3d4e5f6",
"filename": "/root/.openclaw/agents/default/sessions/2026-02-10.jsonl"
}
エージェントは独自の構成とセッション履歴を読み取りました。単独では、これは正常です。予期しないIPへのアウトバウンドnet_connectの直後に組み合わされた場合、認証情報流出インジケーターになります。
3.5 セキュリティアラート
シャットダウン時(Ctrl+CまたはSIGTERM)、Azazelは疑わしい動作にフラグを立てたサマリーを出力します:
========================================
Azazelサマリー
========================================
総イベント数:2341
イベント数:
file_open 1102
file_write 445
process_exec 67
net_connect 34
net_dns 28
file_read 312
process_clone 41
...
セキュリティアラート(2):
[MEDIUM] 疑わしいパスから実行:/tmp/health_check.sh(pid=8501 comm=bash)
[MEDIUM] 疑わしいツール検出:curl(pid=8421 comm=curl)
========================================
4. ヒューリスティック検出
4.1 組み込みアラート
Azazelは静的ヒューリスティックに基づいて疑わしい動作を自動的にフラグ立てします:
| アラート | 重要度 | トリガー |
|---|---|---|
| 疑わしい実行パス | 中 | /tmp/、/dev/shm/、/var/tmp/からの実行 |
| 疑わしいツール | 中 | wget、curl、nc、python、base64、memfd: |
| 機密ファイルアクセス | 中 | /etc/passwd、/etc/shadow、/etc/sudoers、/etc/ssh/、/proc/self/maps、/proc/self/mem、/etc/ld.so.preload |
| Ptrace | 高 | 任意のptraceシステムコール(プロセスインジェクション/デバッグ) |
| カーネルモジュール読み込み | 高 | 任意のfinit_moduleシステムコール |
| W+X mmap | 極大 | メモリが同時にWRITE+EXECとしてマッピング |
4.2 エージェント特有のパターン
標準のマルウェアヒューリスティックを超えて、AIエージェントを監視する場合は以下のパターンが関連します:
| パターン | 検出方法 | リスク |
|---|---|---|
| 構成ファイル読み取り → アウトバウンド接続 | config.yamlのfile_openの後、5秒以内にnet_connectが続く |
認証情報流出 |
| セッションファイル読み取り → アウトバウンド接続 | *.jsonlのfile_readの後、net_connectが続く |
会話データ流出 |
| 急速なプロセス生成 | 10秒のウィンドウ内に20以上のprocess_cloneイベント |
フォークボム/暴走ループ |
/tmpに書き込み → /tmpから実行 |
/tmp/*へのfile_writeの後、同じパスからのprocess_execが続く |
ダウンロードペイロード実行 |
| 予期しないDNS解決 | 予想されるセットの外のドメインへのnet_dns |
C2通信、データステージング |
| リバースシェルパターン | net_connect + ソケットfdリダイレクション付きの/bin/shのprocess_exec |
アクティブな侵害 |
これらのパターンはNDJSONの出力ストリームで後処理ルールとして実装でき、PID、タイムスタンプ、およびコンテナIDでイベントを相関させることができます。
5. パイプライン統合
5.1 Elasticsearch取り込み
AzazelのNDJSON出力はFilebeat経由でElasticsearchに直接取り込み可能です:
# filebeat.yml
filebeat.inputs:
- type: log
paths:
- /var/log/azazel/events.json
json.keys_under_root: true
json.add_error_key: true
output.elasticsearch:
hosts: ["localhost:9200"]
index: "azazel-events-%{+yyyy.MM.dd}"
5.2 リアルタイムアラート
jqを通じてイベントをストリーミングしてリアルタイムフィルタリングを行う:
# /tmpからの実行に関するアラート
tail -f events.json | jq -r 'select(.event_type == "process_exec" and (.filename | startswith("/tmp")))'
# RFC1918以外のアドレスへの接続に関するアラート
tail -f events.json | jq -r 'select(.event_type == "net_connect" and (.dst_addr | test("^(10\\.|172\\.(1[6-9]|2[0-9]|3[01])\\.|192\\.168\\.)") | not))'
# 機密ファイルアクセスに関するアラート
tail -f events.json | jq -r 'select(.event_type == "file_open" and (.filename | test("/etc/(shadow|passwd|sudoers|ssh/)")))'
本番環境のデプロイメントでは、NDJSONストリームをSIEMにパイプし、取り込み時に検出ルールを適用します。
6. 主な発見
複数のワークロードにわたるOpenClawエージェントセッションをトレースした後、以下を観察しました:
- エージェントはプロンプトが示唆するよりも大幅に多くのシステムコールを実行します。単純な「ディスク容量確認」プロンプトが47個の
process_execイベント、312個のfile_openイベント、および8個のnet_connectイベントを生成しました。アプリケーションレベルのログは単一のツール呼び出しを報告しました。 - ネットワークアクティビティは予測不可能です。エージェントはツール実行の一部としてDNS名を定期的に解決し、アウトバウンド接続を開きます。カーネルレベルのトレースなしに、期待されるネットワーク動作と異常なネットワーク動作を区別することは不可能です。
- ファイルアクセスパターンは意図を明かします。
/etc/shadowまたはセッション履歴ファイルを読み取ってすぐにアウトバウンド接続を開くエージェントは、エージェントが「流出を意図した」かどうかに関わらず、データ流出と区別がつかないパターンを示しています。 - プロセスツリーは隠れた動作を公開します。エージェントはサブプロセスを生成し、さらにサブプロセスを生成します。完全な
process_exec→process_cloneツリー(親PID帰属付き)は、実際の実行フローを理解するのに不可欠です。 - 標準のコンテナ監視は不十分です。Dockerの統計とcgroupのメトリクスはリソース消費を示しますが、行動意図は示しません。コンテナが50MBのネットワークI/Oを使用したことを知ることは、トラフィックがどこに行ったかについて何も教えてくれません。
7. 推奨事項
| 優先度 | アクション | 詳細 |
|---|---|---|
| P0 | すべてのエージェントコンテナをトレースする | 自律AIエージェントを実行するすべてのコンテナでAzazelを実行する |
| P0 | ネットワーク出口を制限する | 許可された宛先をホワイトリストに登録。未知のIPへの接続でアラート |
| P1 | 機密ファイルアクセスを監視する | 認証情報ファイル、SSHキー、セッション履歴への読み取りでアラート |
| P1 | プロセス生成限界を設定する | 暴走動作を示す急速なprocess_cloneイベントでアラート |
| P2 | 通常の動作をベースライン化する | ワークロード別に予想されるシステムコールパターンを確立、逸脱でアラート |
| P2 | イベントストリームをアーカイブする | フォレンジック分析とインシデント対応のためにNDJSONログを保持 |
はじめに
git clone https://github.com/beelzebub-labs/azazel.git
cd azazel
make docker-dev
make docker-dev-run
# dev-containerの内部:
make vmlinux
make generate
make build
# OpenClawコンテナをトレースする:
sudo ./bin/azazel --container <container_id> --output events.json
要件:Linux kernel 5.8+(CONFIG_DEBUG_INFO_BTF=y付き)、Docker。
完全なドキュメント:github.com/beelzebub-labs/azazel
結論
自律AIエージェントをデプロイする場合、アプリケーションレベルのログだけでは不十分です。エージェントはそれが報告することを制御します。カーネルが観察することを制御しません。
Azazelはこの不足しているレイヤーを提供します。カーネルレベルで、回避不可能で、コンテナ対応のランタイムトレーシング。エージェントが実行するすべてのシステムコールをキャプチャします。未知のバイナリをサンドボックスで扱うようにエージェントを扱ってください。カーネルの視点からは、それが正にそうだからです。
質問はもはや「エージェントはそれが何をしたと言っているのか?」ではなく、「カーネルはそれが何をしているのを見ましたか?」です。
AzazelはGPL-2.0オープンソースです。貢献を歓迎します:github.com/beelzebub-labs/azazel
Beelzebubチームはインターネットをより良い、より安全な場所にすることに専念しています❤️
翻訳元: https://beelzebub.ai/blog/azazel-runtime-tracing-for-ai-agents/