dazai — burn-after-reading secret (motokano) について
読み取り回数やシェル/SSH セッションに合わせて API シークレットを失効させたい人向けの Rust 製ツールキットです。MCP サーバーはロック済みメモリからシークレットを渡し、セッション終了時に消去してプロセスを終了できます。
主な機能
- 01MCP 経由でシークレットを提供
- 02指定回数の読み取り後にシークレットを消去
- 03ハートビートによるセッション連動
- 04セッション切断時に登録済みエージェントを終了
- 05ロック済みメモリと Linux seccomp による制限
活用シーン
- 01エージェントに一度限りの API シークレットを渡す
- 02シェルや SSH セッション終了時にシークレットを消去
- 03セッション切断後に登録済みエージェントを停止
MCP 対応
`motokano` は設定済みツールを一回限りの MCP サーバーとして公開し、`dazai mcp` は MCP クライアントからプロセス ID を登録してセッション連動の保護を行います。どちらも stdio トランスポートを使用します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
ningen-shikkaku
AI エージェント向けの、読み取り後に消去されるシークレット。
ningen-shikkaku には、2 つの小さな Rust バイナリが含まれています。dazai(セッションに紐づくデーモン)と motokano(一度だけ実行され、自壊する MCP サーバー)です。
MCP の設定には平文の API キーが大量に含まれており、実行するすべてのエージェントがそれらを読み取れます。それらのキーはエージェントの終了後も有効なままです。dazai はこれを逆転させます。シークレットはロックされ、スワップされない RAM に保存され、MCP 経由でエージェントに提供されます。そして、N 回読み取られた後、またはセッションが終了した瞬間に破棄されます。

motokano --calls 1 --tool 'name=get_key,kind=static,value=s3cr3t' --arm
任意の MCP クライアントを接続し、get_key を1 回だけ呼び出すと、s3cr3t を受け取ります。サーバーはロックされたメモリから値を消去し、自身に SIGKILL を送信します。もう一度呼び出すと、プロセスはすでに終了しています。
インストール
# prebuilt binaries (macOS arm64/x86_64, Linux x86_64/arm64)
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/New1Direction/ningen-shikkaku/releases/latest/download/dazai-installer.sh | sh
# or homebrew
brew install New1Direction/tap/dazai New1Direction/tap/motokano
# or from source (required for the Linux seccomp build)
git clone https://github.com/New1Direction/ningen-shikkaku
cd ningen-shikkaku/rs
cargo build --release # -> target/release/{dazai, motokano}
cargo build --release --features seccomp # Linux: seccomp syscall allowlist
ビルド済みバイナリはデフォルトの機能でビルドされています。seccomp で制限されたデーモンを使うにはソースからビルドしてください(libseccomp にリンクするため、まず libseccomp-dev と pkg-config をインストールしてください)。
Claude Code で使う
# a one-shot secret an agent can read exactly once:
claude mcp add burn-once -- motokano --calls 1 --arm \
--tool 'name=get_key,kind=static,value=YOUR-SECRET'
# or the session-bound daemon: agents register their PID and get SIGKILLed
# the moment your session dies
dazai daemon --arm --grace 5 &
claude mcp add dazai -- dazai mcp
どの MCP クライアントでも同じように使えます。トランスポートは通常の stdio です。
第二幕:エージェント向けのデッドマンスイッチ
同じデーモンをセッションのキルスイッチとしても使えます。任意の MCP クライアントが PID を登録します。シェル/SSH セッションが終了したとき、ハートビートが止まったとき、またはパニックシグナルを受信したとき、dazai は登録されたすべてのプロセスに SIGKILL を送り、コンパイラーが最適化で除去できない方法でシークレットを上書きし、終了します。その場を離れれば、エージェントは終了し、シークレットは消去されます。
dazai daemon --ping-timeout 15 # terminal A (dry-run by default; --arm makes it real)
dazai client --interval 5 # terminal B
# close terminal B -> the daemon wipes its secrets and exits
これは自分のマシン上で、自分のシークレットと自分が設定したツールだけを対象に動作します。他のプロセス、ファイル、ホストには一切触れません。
内容
2 つの層で構成されています。
- 強化された Rust デーモンとツール群 — 中核となる実装です。
mlock(スワップなし)、madvise(MADV_DONTDUMP)とprctl(PR_SET_DUMPABLE, 0)(コアダンプ/ptrace なし)、seccomp によるシステムコールの許可リスト(execve/open/connectなどを禁止)、および最適化で除去されないexplicit_bzero/memset_sによる消去を備えています。 - Python リファレンス実装 — この仕組みを確立した、元の概念実証です(
python-reference.mdを参照)。
| コンポーネント | 機能 |
|---|---|
dazai daemon | ウォッチドッグです。mlock されたシークレットと UNIX ソケットのハートビートを保持し、セッションが失われると消去して自壊します。Linux では seccomp で制限されます。 |
dazai client | ハートビートクライアントです。デーモンの動作をシェル/SSH セッションに紐づけます。 |
dazai mcp | デーモンをツールとして公開する MCP サーバーです。任意のエージェントがセッションに紐づく保護のために自身の PID を登録できます(セッションが終了すると SIGKILL が送られます)。 |
motokano | 単独で動作し、自壊する MCP サーバーです。N 回のツール呼び出しに応じた後、シークレットの状態を消去して終了します。 |
| Python reference | secmem.py/deadman.py/heartbeat.py/shellrc.sh — 移植可能な概念実証です。 |
アーキテクチャ
flowchart LR
A["MCP client / AI agent<br/>(stdio transport)"]
subgraph Daemon["dazai daemon (kikka Watchdog)"]
D["dazai daemon<br/>mlock'd SecretBuffers (goodnight)<br/>seccomp-confined on Linux (kekkai)"]
SOCK[("UNIX socket 0600<br/>HELLO heartbeat + REGISTER / ARM / STATUS")]
end
MCPD["dazai mcp<br/>(rei · rmcp server)"]
HB["dazai client<br/>(heartbeat: HELLO / PING)"]
MOTO["motokano<br/>(self-immolating MCP server)<br/>static values in SecretBuffer"]
KILL{{"wipe (explicit_bzero / memset_s)<br/>+ SIGKILL"}}
A -->|"register pid / status / panic"| MCPD
A -->|"get_key (static, N reads)"| MOTO
MCPD -->|"relay verbs + signals via pidfile"| SOCK
HB -->|"holds liveness connection"| SOCK
SOCK --- D
MOTO -. "optional --dazai-socket: register + monitor" .-> SOCK
D ==>|"on trigger: SIGKILL registered PIDs, then wipe + self-SIGKILL"| KILL
MOTO ==>|"after N calls / EOF / daemon death: wipe + exit"| KILL
HB -. "drop / ping-timeout / panic signal" .-> D
Korg との相互運用
dazai daemon と motokano は、Korg の改ざん検知可能な台帳に記録を送れます。--korg-sink PATH(または事前に開いたディスクリプターを指定する /dev/fd/N)を指定すると、arm、session、read、wipe、kill の各ステップにつき、Korg の append 形式のレコードが 1 件ずつ追加されます。レコードに含まれるのは、語彙が固定されたフィールドとカウンターのみです。シークレットの値、長さ、ダイジェスト、ツール名、引数、パス、環境は記録されません。Korg は ningen-shikkaku.lifecycle@v2 エンベローププロファイルを使ってファイルをインポートし、シーケンス番号、ハッシュ、署名を割り当てます。Korg ライフサイクルレコードを参照してください。
脅威モデル
daZai は、平文のシークレットにアクセスできる時間的な窓と攻撃対象領域を縮小し、セッション終了時にシークレットを確実に破棄します。
次の脅威から保護します:
| リスク | 対策 |
|---|---|
| スワップへのシークレットのページング | mlock によってバッファーを RAM にロックします |
| コアダンプへのシークレットの記録 | madvise(MADV_DONTDUMP) + prctl(PR_SET_DUMPABLE, 0)(Linux) |
| セッション喪失後もシークレットが残存すること | ハートビートの途絶/ログアウト → ワイプ + SIGKILL |
| 使用後にシークレットがプロセスメモリーに残存すること | explicit_bzero / memset_s — コンパイラーが省略できないワイプです |
| 制限されたプロセスによる脱出 | seccomp の許可リストが execve / open / connect / ptrace / …を拒否します(Linux) |
| ptraceによるデーモンの盗み見 | prctl(PR_SET_DUMPABLE, 0)(Linux) |
次の脅威からは保護しません(この点について、プロジェクトは意図的に包み隠さず説明しています):
- GPU VRAM。 接続された LLM/エージェントがシークレットを GPU メモリーにコピーした場合、ホストプロセスを終了しても VRAM はワイプされません。daZai が制御するのはホスト RAM と監督下にあるプロセスであり、アクセラレーターのメモリーではありません。
execツールの標準出力。motokanoのkind=execツールはコマンドの標準出力を返します。これは OS によってバッファーリングされ、ロックされたバッファーには保持されません。ワイプの保証が必要な場合は、kind=static(事前に読み込まれた、ロック可能でワイプ可能な値)を使用してください。- マネージドランタイムに残るデータ(Python リファレンス実装)。 CPython は
bytesを自由にコピーするため、シークレットはロックされていないヒープに一時的に存在する場合があります。Rust 実装では独自のバッファーについてこの問題を解消しています(データはロックされたマッピングに書き込まれ、GC ヒープにはコピーされません)。Python の層はリファレンス実装であり、完全な保証ではありません。 - 稼働中のマシン上の特権を持つ攻撃者、または同じ UID の攻撃者(root、
/proc/<pid>/mem、デバッガー)によるワイプ前のメモリー読み取り。mlockはスワップを防ぎますが、メモリーの読み取りは防ぎません。seccomp +PR_SET_DUMPABLEによって Linux での攻撃の難易度は上がりますが、稼働中のマシンへの特権アクセスをすでに持つ攻撃者は対象外です。 - RAM へのコールドブート/DMA/物理的攻撃。
- 致命的なクラッシュ(カーネルの OOM、外部からの
kill -9、電源喪失)。ワイプ処理を実行できないため、何もゼロ化されません。このような状況での仕組みはベストエフォートであり、それ以上の保証をうたうことはありません。
つまり、daZai は、稼働中のマシンをすでに掌握している攻撃者に対する保証ではなく、そのような保証は実現できません。シークレットを一時的かつセッションに紐付いたものにするための鋭いツールであり、制限事項もすべて最初から明示しています。
検証
- Rust ワークスペース全体で81 件のテスト(セキュアメモリー、パニックポリシー、ワイヤープロトコル、MCP 層、ワンショットのライフサイクル、Korg のライフサイクル契約)に加え、Python リファレンス実装の29 件のテスト。
- Linux seccomp は、実際の
KillProcessフィルターのもとで両方のアーキテクチャに対して検証済みです —aarch64(ローカル)およびx86_64(CI)。デーモンが実際のフィルターをインストールし、SIGSYSが発生しない状態で統合テストスイート全体が実行されます。 - すべてのプッシュで、テストスイート全体(デフォルトと
--features seccompの両方)、clippy -D warnings、rustfmt --checkが x86_64 Linux 上で実行され、恒久的なリグレッションゲートとして機能します。
詳細な技術ドキュメント(クレートごとの設計、seccomp の許可リスト、敵対的レビューの履歴)は rs/README.md に、Python の概念実証は python-reference.md にあります。
名前の由来
小説家の太宰治にちなんで名付けられました。作品では、失踪や自己消去をテーマに繰り返し取り上げています。見守られなくなった瞬間に自らを消去することを特徴とするソフトウェアにふさわしい名前です。リポジトリの名前は、太宰の小説『人間失格』(人間失格、Ningen Shikkaku)に由来します。これは雰囲気づくりのためのもので、主義主張ではありません。ソフトウェアは合図に従って自滅するだけです。
ライセンス
MIT © 2026 New1Direction。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。