Claude共有会 / 2026.05.22

AIに自制を
求めるのは
無理ゲー。

じゃあどうやって安全に使い倒すか。現場でやってる事故防止の仕組みと、これからモカの基幹システム(moz)をAIに開放するときの設計の話。専門用語は出てきたら都度説明します。

00 / なぜこの話をするか

セキュリティは
モカの事業の根幹
に効く話だから。

「あったら便利」じゃなく「無いと終わる」レベルで重要。今日30分使って、全員と土台を握りたい。先にその理由を5つだけ。

① モカは信頼資本で食ってる会社

クリエイターの個人情報、契約金額、クライアントとのNDA案件、内部のSlackログ。これらは SaaSの機能比較表に出てこない、見えない資産。一度漏れたら関係性が一発で壊れる業界にいる。信頼を構築するのに3年、失うのに3秒。

② 扱ってるデータが重い

一個でも外に出たら、ニュースになるレベル。

③ AI時代に「事故の種類」が変わった

これまで

人間が「うっかり」やらかす。
1人の操作ミス、1ファイルの誤送信。被害は局所的

これから

AIエージェントが「自走で」やらかす。
1コマンドで テーブル50個を消す、APIキー1個で 全クライアントデータを取得する。被害が 非局所

暴走するAIに対して、人間の「気をつけて」では追いつかない。仕組みで止める時代に入った

④ CEO本人ですら、今日2件やらかしてた

この資料を作る過程で自分の環境を点検したら、~/.claude/settings.local.jsonAPI Key と WordPressパスワードが平文で2件 出てきた。ローテーション済み。経営者でこれ。誰にでも起こる という前提で対策しないと意味がない。

⑤ もうすぐ mozMCP化が始まる

基幹システム(取引先・案件・財務・クリエイター65万件)を、AIから自然言語で操作可能にする計画が今動いている(後でデモする)。AIが基幹DBに触れる時代に入る前に、「正しい縛り方」を全員で握っておきたい。後から「あの時やっとけば」では遅い。

便利に使う、と、安全に使う。
これを同時に握る。 // 今日の30分で、この2つのバランス感覚を共有する
01 / 仕組みで止める

プロンプトで縛るな、
ハーネスで止めろ

ハーネス = AIを動かしている外側の仕組み(Claude Codeそのもの)。AIに「危険なコマンドは慎重に」とお願いするより、ハーネス側で物理的にブロックする方が確実です。ATMに引き出し上限があるのと同じ発想。

具体的にやってること

Claude Codeには PreToolUse Hook(コマンド実行直前に自動チェックを挟む機能)があります。私の環境では、以下のコマンドは正規表現で問答無用にブロック:

AIが「実行します」と判断しても、フックが {"decision": "block"} を返すと実行はキャンセルされる。プロンプトは破れるが、フックは破れない

実際のhook(~/.claude/settings.json)

{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Bash",
      "hooks": [{
        "type": "command",
        "command": "INPUT=$(cat); CMD=$(echo \"$INPUT\" | jq -r '.tool_input.command');
if echo \"$CMD\" | grep -qiE '(rm\\s+-rf\\s+/|drop\\s+database|drop\\s+table|truncate\\s+table|--force\\s+push.*main)'; then
  echo '{\"decision\":\"block\",\"reason\":\"危険なコマンドを検出\"}'
else
  echo '{\"decision\":\"approve\"}'
fi"
      }]
    }]
  }
}

Auto Mode × フックの二段構え

① Auto Mode

defaultMode: auto で許可プロンプトを最小化。Claudeが止まらないので生産性は最大化。

② PreToolUse Hook

Auto Modeで自由に動いても、本当に危険なものだけは正規表現で叩き落とす。速度と安全の両立

配布プロンプト: ハーネスを自分の環境に入れる

自分でhookを書くのは面倒なので、Claude Code自身に書かせます。下のプロンプトをコピペすれば、上で説明した危険コマンドブロックhookが ~/.claude/settings.json に自動で追加されます。

配布ファイル: ~/Downloads/install_harness_hook_prompt.txt

私の ~/.claude/settings.json に、危険なBashコマンドを実行直前に
自動ブロックする PreToolUse hookを追加してください。

【ブロック対象】
1. ルート直下を全消去する rm -rf 系
   - rm -rf / または rm -rf /var, /etc, /Users 等の絶対パス削除
2. データベース破壊系
   - DROP DATABASE / DROP TABLE / TRUNCATE TABLE
3. Gitのmain履歴上書き
   - git push --force ... main
   - git push --force-with-lease ... main

【実装ルール】
- 既存の settings.json は壊さず、hooks セクションだけマージする
- matcher は "Bash"
- ブロック時: {"decision":"block","reason":"危険なコマンドを検出しました"}
- 通過時: {"decision":"approve"}
- 正規表現マッチには jq + grep -qiE を使う

【完了後にやること】
1. 追加後の hooks セクションを見せる
2. ブロックされるコマンドの例で本当に止まるか実演する
   (例: echo "rm -rf /" を挟んで安全に検証)
3. 誤ブロックがないかも確認

実行してください。

実行後の効果

02 / その場で実演

自分の環境に
シークレット
平文で残ってないか

シークレット = APIキー・パスワード・トークン等の認証情報。本来は暗号化された場所か環境変数に置くべきものが、設定ファイルやシェル履歴に そのまま生の文字列で残ってないか を全員でチェックします。たぶん1人1個は出ます。私自身、調査して2件見つけて冷や汗かきました。

3ステップでできる

  1. 下のプロンプトをコピー
  2. 自分のClaude Codeにペースト
  3. 結果をシェア(マスク表示されるので画面共有しても安全)

配布プロンプト

配布ファイル: ~/Downloads/secret_scan_prompt.txt

私の環境にAPIキー・パスワード・トークン・秘密鍵が
平文で残っていないかをチェックしてください。

【点検する場所】
- ~/.claude/settings.json
- ~/.claude/settings.local.json
- ~/.zshrc / ~/.bashrc / ~/.bash_profile
- ~/.zsh_history(最後の3000行)

【検出パターン】
- Anthropic API Key (sk-ant-api...)
- OpenAI / Google / AWS / GitHub / Slack のAPIキー
- WordPress App Password(4文字×6スペース区切り)
- 秘密鍵(-----BEGIN ... PRIVATE KEY-----)
- password= / passwd= の平文

【報告ルール】
- 実際の値は絶対に全文出力しない(先頭8文字+...でマスク)
- ファイルパス:行番号:種類:マスク値 の形式
- 各ヒットに修復アクション併記
- ヒットゼロなら「クリーンです」と1行で報告

こんな結果が返ってくる

シークレットスキャン結果: 2件ヒット

1. ~/.claude/settings.local.json:24
   種類: Anthropic API Key
   値: sk-ant-a...(マスク)
   対応: console.anthropic.com で revoke
         → 環境変数 ANTHROPIC_API_KEY に退避

2. ~/.zshrc:42
   種類: WordPress App Password
   値: tgln EOX...(マスク)
   対応: WP管理画面で再発行 → ~/.netrc に退避

なぜ漏れるのか(2大漏洩源)

① 許可ボタンの盲点

Claude Codeが「このコマンド許可しますか?」と聞いてくる時、コマンドにシークレットが含まれた状態で許可ボタンを押すと、そのまま settings.local.json の許可リストに焼き付く。次から聞かれず便利だけど、鍵も一緒に保存される。

② シェル履歴

ターミナルで curl -u user:pass ...export KEY=... をワンライナーで流すと、~/.zsh_history永続的に残る。Gitに上げてないからセーフ、ではない。

シークレットは
「うっかり」でしか漏れない。 // だから定期スキャンを儀式にする
03 / moz MCP化計画

基幹DBをAIに開放する
多層防御の設計

いま、モカの基幹システム(取引先・案件・財務・クリエイター65万件)を MCP(AIアプリから外部システムを操作するための共通プロトコル)で公開する計画を進めてます。便利な反面、AIが暴走したらデータが消える。だから設計時点で防御を4層重ねます。

全体アーキテクチャ

[Claude Code / Claude Desktop]
        │  stdio
        ▼
[ブリッジプロセス (Node.js)]
        │  HTTP SSE + Bearer PAT
        ▼
[Heroku: moz-mocha Laravel]
        │  /mcp エンドポイント
        │  Sanctum認証 → ability → is_admin → 実行
        ▼
[McpToolService]
        │
        ├─ PostgreSQL(DB操作)
        ├─ Redis Queue(bulk処理)
        └─ mcp_audit_logs(全書き込み記録)

防御① 認証・認可の3層構造

ユーザーごとに PAT(Personal Access Token = 個人専用トークン)を発行。トークンには ability(権限ラベル)を付けて、できる操作を限定します。

仕組み役割
1. 認証 Sanctum PAT(90日有効・ハッシュ保存) 誰のリクエストか特定
2. 認可(権限) ability制 resource:action 例: projects:write = 案件の書き込み権
3. 認可(管理者) destructive操作は is_admin=true 必須 トークン漏洩時の被害を局所化

PATが万が一漏れても、abilityが付いてなければ何もできない。さらに削除系は 管理者ユーザーしか実行できない。abilityチェックを通過しても is_admin=false なら403。

防御② 取り返しのつかない操作は2段階フロー

削除・失注マーク・入金済みマークは、いわゆる destructive 操作(戻せない操作)。AIに一発で実行させず、dry-run → 人間確認 → 本番実行を強制します。

Step 1 AIがツール呼び出し(confirmなし) dry-run実行(DBは変更しない) 「23件の関連メモが道連れで消えます」など影響範囲を返す Step 2 AIがユーザー(人間)に確認を求める ユーザー承認 Step 3 AIが confirm=true で再呼び出し 本番実行 + 監査ログ記録

AIのループ誤動作で取引先テーブルが空になる事故を、構造的に 防ぐ。

防御③ レート制限(暴走対策)

操作分類上限狙い
SAFE 読み取り300 req/分サーバー負荷防止
NORMAL 書き込み60 req/分大量誤登録の防止
DESTRUCTIVE20 req/分(固定窓)削除ループの早期遮断
bulk_create(一括)5 req/分キュー詰まり防止

防御④ 全書き込みを監査ログに残す

「誰が・いつ・どのツールを・どの引数で・dry-runか実行か」を mcp_audit_logs テーブルに全件記録。事故が起きた時に巻き戻せます。

CREATE TABLE mcp_audit_logs (
    id          BIGSERIAL PRIMARY KEY,
    user_id     BIGINT REFERENCES users(id),
    tool_name   VARCHAR(100) NOT NULL,   -- 例: projects.create
    params      JSONB,                    -- 引数(PAT・パスワードは除外)
    result      JSONB,
    dry_run     BOOLEAN DEFAULT FALSE,
    confirmed   BOOLEAN DEFAULT FALSE,
    ip          VARCHAR(45),
    created_at  TIMESTAMP NOT NULL DEFAULT NOW()
);
設計の原則: MCPはあくまで既存ビジネスロジックの上に乗る薄い層。フォロー日計算は ScheduleCalculatorService 経由必須、ステータス変更メモは既存ルールを継承、クリエイター指標更新はCSVインポートのみ。バリデーションをバイパスする抜け道は作らない
04 / それで、動くの?

設計だけ語っても
説得力が弱いので、
今日 moz に実装した。

設計書を眺める会じゃ意味がない。共有会のために、最小スコープ(読み取り3ツール)で実装してきました。約3時間の作業。これから皆さんの前で動かします。

追加・変更したファイル

ファイル役割規模
app/Services/McpToolService.php3ツールのビジネスロジック約140行
app/Http/Controllers/McpController.phpJSON-RPC 2.0ハンドラ + ability check約100行
app/Console/Commands/McpIssueToken.phpPAT発行 artisanコマンド約60行
routes/api.phpPOST /api/mcp 追加+3行
app/Models/User.phpHasApiTokens trait追加+2行
composer.jsonlaravel/sanctum 追加+1依存

合計 約300行 のコードと、Sanctumライブラリ1個。これだけで基幹DBがAIから操作可能になる。

PAT発行はartisanコマンド一発

$ docker compose exec app php artisan mcp:issue-token \
    --user=1 \
    --abilities=clients:read,projects:read,financials:read

============================================================
MCP PAT を発行しました
============================================================
User       : 岡崎耕平 (id=1, is_admin=true)
Abilities  : clients:read, projects:read, financials:read
Expires    : 2026-08-20 11:11

Token (平文・1回限り表示):
1|reXabZH4GZ2iZuvuYWoOSh0xzua1zxNI3uMQCHHgb...

デモ① 経営サマリーを聞く

Question

「moz経由で、今月の売上目標と実績、達成率を教えて」

Claude の動き

[financials.get_summary を呼んだ]
{
  "year_month": "2026-05",
  "revenue_target": 19600000,
  "revenue_actual": 25270000,
  "achievement_rate_pct": 128.9,
  "gross_profit_actual": 7220000,
  "gross_profit_rate_pct": 28.6
}

→ 今月は目標1,960万に対し実績2,527万、
  達成率128.9%です(粗利率28.6%)。

デモ② 優先取引先を聞く

Question

「優先度Sの取引先を見せて」

Claude の動き

[clients.list を priority=S で呼んだ]
{
  "total": 1,
  "clients": [{
    "id": 254,
    "company_name": "ナッシュ株式会社",
    "type": "client",
    "priority": "S",
    "status": "brief_received",
    "next_follow_up_at": "2026-03-26",
    "user": { "id": 3, "name": "栗原龍司" }
  }]
}

デモ③ Ability制御の実演(ハイライト)

「鍵に権限ラベルをつける」設計が本当に効くか、その場で見せます。financials:read のみの制限トークンを発行し直して、わざと clients.list を呼ばせます。

✅ 許可された呼び出し

financials.get_summary
→ { "achievement_rate_pct": 128.9, ... }
  正常に返却

❌ ブロックされた呼び出し

clients.list
→ {
  "error": {
    "code": -32003,
    "message": "Forbidden:
      このトークンには
      clients:read の権限が
      ありません"
  }
}

これが「PAT × Ability × is_admin の3層」の実物。トークンが漏れても、abilityがなければ何もできない。

今日の実装に入ってないもの(次フェーズ)

05 / Takeaway

持ち帰り4行

明日から自分のClaude Code環境に効く話。

01

AIに自制させるな、ハーネスで止めろ

PreToolUse hookで危険コマンドを正規表現ブロック。プロンプトは破れるがフックは破れない。

02

シークレットスキャンを儀式にする

月1で配布プロンプトを流すだけ。許可ボタンとシェル履歴という2大漏洩源を定期点検。

03

PAT × Ability × is_admin の3層認可

destructive操作だけ管理者必須にすれば、トークン漏洩時の被害が「読み取り+一部書き込み」で止まる。

04

Dry-run → Confirm の2段階フロー

削除系はAIに一発で実行させない。「23件が消えます」を人間に見せてから実行する。