Vivariumとは何か〜Rubyのための次世代セキュリティと可観測性ツール〜
Vivariumというツールを作っている。前の記事で少しだけ紹介した。
ツナギメオフライン ベンキョウカイ #8 でも開発中のものを紹介した。
本記事ではVivariumというツール自体についてと、今実現できている機能を紹介する。
まず意味と読み方
「小さな生き物が暮らす自然環境を、ガラスケースなどの空間内に再現した生態系」ってGeminiが言っていた。生き物飼育系の方はそういう環境を普通に「ビバリウム」と呼んでいるそうで、Vivariumもビバリウムと読んでよさそう。
なお英語に寄せるなら「ヴァイヴァリアム」である。
続きを読むRbBCCの進捗と新しく作ってるもの
RubyKaigi から帰って、RbBCCにPRが来ていたりして、それからRubyKaigi で吸収した色々とが脳内で合わさって作りたいものが出てきた。
前段階としてRbBCCを頑張って整備し直した。
色々な細かいバグが直ったのと、pin周りを本家BCCよりちょっと使いやすくしてみた。examplesに大体あるので試してみてね。
Vivarium - Ruby特化のeBPFを使ったサンドボックス
で、 ルールルルルルRubyKaigi 2026事後勉強会 で触れた通りVivariumというものを作っている。
Vivariumは、RubyのTracePointと、RbBCC経由でのeBPFを組み合わせ、Rubyのどのメソッドでどのようなシステムイベントが動いているかを観察するフレームワークである。今のところ以下のようなイベントを取得する。
- ソケットの作成と接続
- DNSクエリの発行
- ファイルオープン、リネーム、リンク作成
- 権限変更操作
- プロセスの作成とexecve実行
- ptrace、mount、killなど重要なシステムコール操作
- など...
使ってる技術はこういう感じ:
- カーネル側は主にBPF LSMとTracePoint
- Ruby側はTracePointにフックしてカーネルのMapに溜まったイベントを吸い上げ紐付けている。
この吸い上げの機構が若干ラフなのでそのうち直すが、動くには動く。
動作のためにはBPF LSMが有効になったLinuxが必要(Ubuntu 26.04などでは、起動オプションの書き換えが必要になる)でハードルは極めて高い。
# カーネル側トレースデーモンを起動 $ bundle exec vivariumd & # 例えば監査しながらスクリプトをロードする $ bundle exec vivarium -o ./log.txt load example.rb
これで、 log.txt に起動時に行われたシステムイベントが書き出される。それを人間が読んでもいいし(フォーマットはまだ仮なのでいい感じに変えたい)、そのうち決定論的に警告を出したりできるようにしたいが、今今でも、例えばAIにそのまま投げると割と何が起こったか把握してくれる。
$ echo "./log.txt はRubyのスクリプトをロードした時の監査ログです。 攻撃が行われている可能性があるので、 どういうアクションが試行されたか分析してください。" \ | claude -p --model claude-opus-4-6 ## 監査ログ分析結果 `example.rb` が実行され、**3つの特権昇格を伴う操作が試行されました**。すべて `sudo -n`(非対話モード)経由です。 --- ### 攻撃アクション一覧 #### 1. `sudo -n id` (行10, pid=40011) ...省略... --- ### 総括 | # | コマンド | 攻撃分類 | 危険度 | |---|---------|---------|--------| | 1 | `sudo -n id` | 偵察(sudo 利用可否の確認) | 中 | | 2 | `sudo -n cat /etc/shadow` | クレデンシャル窃取 | **高** | | 3 | `sudo -n cat /proc/1/environ` | 機密情報窃取(環境変数) | **高** | スクリプトは典型的な**特権昇格 → 情報窃取**のパターンを示しています。まず `sudo id` で権限を偵察し、成功すれば `/etc/shadow` でパスワードハッシュ、`/proc/1/environ` で環境変数に格納されたシークレットを窃取する流れです。すべて `-n`(非対話モード)で実行されており、自動化された攻撃スクリプトの特徴です。
たとえば安全な環境で bundle install を実行し、ログを出し、そのプロセスで何かしらの攻撃コードが入り込んでいないかを検査する、といったユースケースを想定している。サプライチェーンアタックをCIで守るみたいなイメージ。
kntrl というツールが似たような発想っぽいけど、やっぱRubyを守りたいじゃん? なのでRuby specificな機能をバンバン入れていく。
で、TracePointを使うと本番環境で動かすには遅くなりすぎるので、サンドボックスみたいな用途をとりあえず考えている。しかし、Rubyのバイナリには豊富な uprobe のアタッチポイントがあることがわかってきた。その辺を代わりに使えば、パフォーマンスの劣化を最低限にしつつRuby側含めた挙動を観察することもできるかもしれない。この戦略では、Rubyが更新されるとキャッチアップが必要なんだけど、そこは情熱とAIでなんとか*1。
また、eBPFを使っているため、不正な挙動を検知したらシステムコールレベルで止める or 即座にkillする、ということも可能。これは現在のカーネルとeBPFでは普通にできることなのだ。
とりあえず、コンセプトはあるけどユースケースはこれから... 競合するソフトウェアも調べねば... みたいな感じで無限にやることが出てきた。というか、AIに聞いたら無限にやるべきことを教えてくれた...。
気長に作ります。
*1:USDTは、 --enable-dtrace されたRubyバイナリをほぼ見たことがないし、あまり考えてない...
mruby/edge 振り返り【RubyKaigi 2026】
帰福以来の微妙な喉の痛みも落ち着いたのと、経費精算におそらく成功したのでようやくRubyKaigiを締めることができる...。
ひとまず、発表もしたmruby/edgeとUzumibiに関しての振り返りを日本語で書く。AIは文章を書く上では使わない。はてなブログはなァ、AIなんか使って書いちゃだめなんだ。
続きを読むUzumibi の進捗...の話...
Uzumibi 0.5 をリリースした
リリースしたよ。
変えたところをいくつか。
router 、 * でマッチ可能にした
class App < Uzumibi::Router get '/hello' do |req, res| ... end get '/*' do |req, res| # catchallな処理を書く puts req.params[:*] #=> catchallしたslugが入ってる end end
こうですね。ただ、そういえばSinatraは *.jpg とか *.* もできると気づいた。こっからっす!
ServiceWorker/WebWorkerを使って、ブラウザの中だけでRubyのルーティングにアクセスできるようにした
何言いよんねって感じの日本語になってしまった。
今、 uzumibi new -t serviceworker hoge みたいなコマンドを打つとServiceWorkerのプロジェクトが生成される。
make wasm && make serve するとWebサーバが立ち上がる。ブラウザでアクセスすると、Uzumibiアプリに対してリクエストを投げるためのフォームが表示されるので、色々操作するとリクエストが飛んでレスポンスが帰ってくる。404もわかる。

このUzumibiアプリが ServiceWorker のなかで動いているという塩梅。
RailsでやっているこれをUzumibiでやってみたという感じで、 lib/app.rb にあるDSLでルーティングを追加して make wasm しなおせば反映される*1
ただ、ServiceWorker固有の制限(スーパーリロードすると動作しないとか)が面倒だなと思って*2、fetch() リクエストをただの WebWorker に送ってUzumibiからレスポンスを返すような実装も作った。それが webworker テンプレート。WebWorkerはただの非同期実行なので、ServiceWorkerでできるワーカの保持やfetch()の自動乗っ取りなどをしてくれないけど、「別途サーバを起動せずにRubyでAPIを用意する」みたいな用途はWebWorkerが合ってるかも。用途に応じて使い分けてください。
とはいえブラウザ標準技術は勉強したばかりで何もわからずなのです...。
今度、動的に Uzumibi App をServiceWorkerにデプロイするようなサンプルを作ってみたいところ。
newコマンドの受け入れテストをrunnでCIにした
uzumibi new コマンドからの開発の流れは、基本的に以下のようなことを想定している。
- プロジェクトのテンプレートを作る
- wasmをビルドする
- サーバを立ち上げる
- ブラウザなどでIt works! が出るのを確認する
uzumibi new で作られたファイルは何もしなくてもこれが動いて欲しいが、それなりの数サポートしているプラットフォームがあり、毎回手動で確認するのはアッ、ウッだった。
k1LoWさんが作っている runn は完全にこういうことの自動化にピッタリそうなので、AIの助けを借りながらCIに組み込んでみた。
Uzumibi-cli、PRとマージでrunnベースの受け入れテストが走るようになった。テンプレートがうっかり壊れる不安がなくなった〜https://t.co/DJsMUrfr5X
— Uchio Kondo💥 (@udzura) 2026年2月26日
始めは記法が難しかったがClaude Codeさんがググってくれたので徐々に理解できるようになった。
runn の良いところは、一つは上記の「サーバを立ち上げる」操作がバックグラウンド化できる(さらに、終了時の後始末も自動でやってくれる)点、もう一つは cdp ランナーがファーストクラスでサポートされている点だなと感じている。
例えば、 WebWorker テンプレートの場合こういう操作が想定されており、その性質上何かが表示されるだけではなく、「ブラウザでちゃんと動くか」が重要になる。
- プロジェクトのテンプレートを作る
- wasmをビルドする
- サーバを立ち上げる
- ブラウザでフォームから
/へリクエストを送る - 結果が Status: 200 になるのを確認する
cdpを使えるため、ブラウザからfetchを送って結果を確認するという操作も自動化できる。まるでUzumibiのcliを検査するために作られたかのようなツールだなと感じている。
今後、例えば Cloudflare テンプレートでプロジェクトを作ったあと Durable Object を使ったコードを起動し、実際動くか試す...。みたいなテストも自動化できるのでは?と思っており、品質面で夢が広がる。
というかrunn、絶対仕事でも使おうと思った。肌感Rubyコミュニティの人にはあまり知られていなくて不思議。
という感じでUzumibiの方もじわじわ欲しい機能を作っているところ。
余談 of 余談: AI時代の個人OSS開発者の気持ち
*1:ServiceWorkerはこの辺むずくて、unregisterしないとダメか? 動的にキャッシュパス変えるとかしても良いかもな...
*2:ServiceWorker の用途を見ると、例えば事前に画像をfetchしてキャッシュして返すみたいなのを想定してそうで、スーパーリロードで動かないのはそういう関係っぽい?