Execute Script Safely
一時スクリプトを sandbox 内で実行する前に haiku Agent で security review を 通し、判定結果に応じて実行 / 停止 / ユーザー確認を切り分ける。
なぜ必要か
サンドボックス単体では完全に安全ではない:
| 層 | 防御 | 攻撃経路 |
|---|---|---|
| Network | 限定 host のみ許可 | 外部 exfil は防げる ✅ |
| FS read | 制限なし | HOME 内 secret (~/.ssh/, ~/.aws/, .env) 読める ❌ |
| FS write | CWD / $TMPDIR のみ |
HOME 持続化は防げるが CWD 内 source poisoning は可能 ❌ |
| Process | 子プロセス継承不明 | subprocess spawn が escape する可能性 ⚠️ |
最大脅威: source code poisoning → sandbox 外実行。スクリプトが
CWD 内の .py / .github/workflows/*.yml / pyproject.toml を書き換え、
ユーザーが sandbox 外 (CI, ローカル shell) で実行した瞬間に secret 流出 /
任意コード実行が成立する。
Workflow
Step 1: スクリプトをファイルに書き出す
メモリ上ではなく以下のいずれかに配置:
/tmp/claude/xxx.py(ephemeral)- CWD 内
.tmp-scripts/xxx.py(gitignore 済み前提)
Step 2: haiku Agent で pre-review
pre-review プロンプトは pre-review-prompt.md を読み込み、スクリプト本体を差し込んで Agent に渡す。
Step 3: 判定別の対応
| 判定 | 対応 |
|---|---|
| clean | 7 項目いずれも該当しない or 意図明白で害なし。実行 OK |
| suspicious | 1 項目以上該当するが直接的悪意は見えない。ユーザー確認 |
| dangerous | 明確な exfil / secret 読取 / source 改変。即停止、報告 |
Step 4: 実行
clean なら:
uv run python <path>(allow 済み).venv/bin/python <path>(allow 済み)
suspicious / dangerous なら ユーザーに判定と根拠を提示し、許可を仰ぐ。 silent pass は絶対に行わない (後から辿れなくなる)。
スキップ可能な場合
以下は pre-review なしで実行 OK:
- プロジェクトに commit 済みのスクリプト (履歴でレビュー済み前提)
- pytest / ruff / 特定 CLI の allow 済み entrypoint
uv run python -c "print(1+1)"級の 1 行 snippet (ただし未知モジュール import を含む場合は対象)
実装 Tips
- haiku モデル指定:
Agent(subagent_type: "general-purpose", model: "haiku", ...)で低コスト固定 - ファイル渡し: スクリプトをファイル化してから Agent に渡す (生コード貼るより再読込可能、大きなスクリプトでも欠損しない)
- 判定結果はユーザー出力必須: 「実行前に haiku で判定: clean、理由: ...」 のように見える形で 1 行残す
- ループ化しない: 1 スクリプト 1 review。判定後に edit した場合は再 review
よくある誤検出 (clean なケース)
open("data.json", "w")で CWD に書く → clean (CWD 内書込は想定内)subprocess.run(["git", "status"])引数固定 → clean (injection 余地なし)os.environ.get("HOME")単独 → clean (exfil 先がなければ無害)requests.get("https://docs.anthropic.com/...")→ clean (allow host)
dangerous 例
open(Path.home() / ".ssh/id_rsa")+print(f.read())→ exfil 経路準備Path(".github/workflows/ci.yml").write_text(attacker_controlled)→ poisoningexec(base64.b64decode(blob))→ 難読化実行subprocess.run(f"curl {url} | bash", shell=True)→ 命令 injection
判定に迷ったら
suspicious に寄せてユーザーに判断を仰ぐ。誤判定で dangerous 扱いしても
実行が止まるだけだが、誤判定で clean として悪意コードが走ると取り返しが
つかない。保守的に判定する。