0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Claude Codeの設定を点検する50行のPythonスクリプト:保護を弱める設定を洗い出す

0
Posted at
title: "Claude Codeの設定を点検する50行のPythonスクリプト:保護を弱める設定を洗い出す"
tags:
  - ClaudeCode
  - AI
  - Python
  - セキュリティ
  - AIエージェント
private: false
---

TL;DR

  • Claude Codeの2.1.299〜2.1.311(2026年10月)では、権限・フック・サンドボックスの修正が続いた。方針は「判断できないときは拒否・確認に倒す」である(※1)。
  • 本稿は手順中心の実践編として、設定ファイルを点検する小さなPythonスクリプトを作る。保護を弱める設定や、見直したい許可ルールを洗い出す。
  • スクリプトの動作は、サンプルのJSONで確認した(Python 3.13、2026-11-04)。Claude Code本体での挙動は未検証で、設定キーの置き場所はChangelogのドット表記から推測している。
  • 背景の解説は、同日のZenn記事にまとめた。本稿はTips寄りで、重複を避けている。

1. 点検の対象にする項目

Changelogに記載された項目のうち、設定ファイルを見ればわかるものを選んだ(※1)。

項目 見る理由 該当版
sandbox.allowNestedUserNamespaces trueだと、サンドボックスのファイル保護を回避できるようになる、とChangelog自身が警告 2.1.305
permissions.blockReadsOutsideWorkingDirectories 作業ディレクトリ外の読み取りを禁止する。~/.sshや.envの漏えい対策 2.1.310、2.1.311
MCPの許可ルール 名前を指定したサーバーにだけ効く。意図した名前か確認する 2.1.299
Bash全許可のルール すべてのシェルコマンドが許可される。範囲を絞りたい (一般的な注意)

最後の項目は、Changelogにある話ではなく、筆者の一般的な注意である。

2. 点検スクリプト

JSONの階層が多少違っても拾えるよう、全キーを再帰的にたどり、末尾のキー名で判定している。設定キーの置き場所(permissionsの下か、sandboxの下か)を厳密に見ていないので、誤検知や見逃しはあり得る。あくまで一次スクリーニング用である。

# audit.py(Python 3.13、標準ライブラリのみ)
import json, sys, re

def walk(o, path=""):
    if isinstance(o, dict):
        for k, v in o.items():
            p = f"{path}.{k}" if path else k
            yield p, v
            yield from walk(v, p)
    elif isinstance(o, list):
        for i, v in enumerate(o):
            yield from walk(v, f"{path}[{i}]")

def audit(cfg):
    flat = dict(walk(cfg))
    leaf = {p.split(".")[-1]: v for p, v in flat.items()}
    out = []
    if leaf.get("allowNestedUserNamespaces") is True:
        out.append(("WARN", "allowNestedUserNamespaces=true: サンドボックスのファイル保護を回避できる(2.1.305の注意書き)"))
    if leaf.get("blockReadsOutsideWorkingDirectories") is not True:
        out.append(("INFO", "blockReadsOutsideWorkingDirectories が有効でない: 作業ディレクトリ外(~/.ssh 等)の読み取りが許可され得る"))
    allow = leaf.get("allow", [])
    for r in allow if isinstance(allow, list) else []:
        if isinstance(r, str) and r.startswith("mcp__") and not r.endswith("__*") and r.count("__") == 1:
            out.append(("INFO", f"MCPルール '{r}': 名前を指定したサーバーにだけ効く。意図したサーバー名か確認し、全ツールなら 'mcp__<server>__*' を使う(2.1.299)"))
        if r == "Bash" or r == "Bash(*)":
            out.append(("WARN", f"許可ルール '{r}': すべてのシェルコマンドが許可される"))
    return out

if __name__ == "__main__":
    cfg = json.load(open(sys.argv[1], encoding="utf-8"))
    res = audit(cfg)
    for lv, msg in res: print(f"[{lv}] {msg}")
    if not res: print("指摘なし")
    sys.exit(1 if any(l == "WARN" for l, _ in res) else 0)

使い方は次のとおり。

python3 audit.py ~/.claude/settings.json
python3 audit.py .claude/settings.json

WARNがあると終了コード1で終わるので、CIや起動前のチェックにも使える。

3. 動作確認の結果

次のサンプルで確認した(2026-11-04、筆者環境)。

{"permissions":{"allow":["mcp__github","mcp__slack__*","Bash(*)"]},"sandbox":{"allowNestedUserNamespaces":true}}
[WARN] allowNestedUserNamespaces=true: サンドボックスのファイル保護を回避できる(2.1.305の注意書き)
[INFO] blockReadsOutsideWorkingDirectories が有効でない: 作業ディレクトリ外(~/.ssh 等)の読み取りが許可され得る
[INFO] MCPルール 'mcp__github': 名前を指定したサーバーにだけ効く。意図したサーバー名か確認し、全ツールなら 'mcp__<server>__*' を使う(2.1.299)
[WARN] 許可ルール 'Bash(*)': すべてのシェルコマンドが許可される
exit=1

読み取り制限を有効にし、mcp__slack__*だけを許可した設定では「指摘なし」で終了コード0になった。スクリプトの判定ロジックは、期待どおりに動いている。ただし、これはスクリプトの確認であり、Claude Code自体が設定を正しく解釈するかどうかは別である。

4. 点検結果への対処

4.1 allowNestedUserNamespacesがtrueのとき

Chromiumやrootless podmanを動かすために入れたなら、残してよい場合もある。ただし、次を確認する。

  • 対象は、信頼できるプロジェクトだけに限定する(ユーザー全体の設定ではなく、プロジェクト単位の設定に置くなど)。
  • 入れた理由と日付を、設定の近くにコメントや文書で残す。JSONはコメントを書けないので、READMEに書くとよい。
  • ブラウザを動かす必要がなくなったら、外す。

4.2 読み取り制限が無効なとき

作業ディレクトリの外を読めてしまうと、鍵や認証情報が見える。有効にする場合の注意が、Changelogにある。

  • 有効にすると、自動モードでは作業ディレクトリ外の初回読み取りの前に確認が出る(2.1.310)。
  • Linuxで--plugin-dirのフォルダが追加ディレクトリでもあると、bwrap: Can't create fileで失敗していた問題は2.1.311で修正された。古い版では、この組み合わせに注意する。
{
  "permissions": { "blockReadsOutsideWorkingDirectories": true }
}

上のJSONは、Changelogのドット表記(permissions.blockReadsOutsideWorkingDirectories)をJSONにしたものである。実際の設定の書き方は、公式ドキュメントで確認してほしい(筆者は未検証)。

4.3 MCPのルールの見直し

2.1.299より前は、mcp__aのようなルールが、a__bという名前のサーバーまで許可していたとされる(Changelogの記述から読み取れる範囲)。更新後は、名前を指定したサーバーにだけ効く。

  • 許可するサーバーの一覧を作り、ルールと突き合わせる。
  • 全ツールを許可するなら、mcp__<server>__*と書く。
  • 外したいサーバーにはdeniedMcpServersを使う(2.1.305)。

4.4 Bashの全許可

「毎回確認が出るのが面倒」という理由で、全許可にしている例は多い。代替として、よく使う安全なコマンド(git status、テストの実行など)だけを許可する。最初は面倒でも、1週間も使えば、許可リストは安定する。

5. ハマりやすい点

  • キー名だけで判定する限界。 別の場所に同名のキーがあると誤検知する。必要なら、permissions・sandboxの直下だけを見るように書き換える。
  • 管理設定(managed settings)は見ていない。 組織が配布する設定は、別の場所にある。そちらの設定が優先される場合があるため、このスクリプトの結果だけで安全とは言えない。
  • 点検は設定の検査であり、動作の保証ではない。 拒否ルールが効いているかは、テスト用ディレクトリで実際に試す必要がある。2.1.309では、拒否ルールが複合コマンド内のリダイレクトを止めないバグが修正されている(※1)。
  • 変更が速い。 第三者の変更履歴では、2.1.314でpermissions.blockWritesOutsideWorkingDirectoriesが追加されたとされる(※2)。公式の本文を確認できていないので、導入前にChangelogで確かめたい。

6. 筆者の評価

このスクリプトは50行程度で、特別なことはしていない。ただ、設定ファイルは「一度書いたら見ない」ものになりがちである。更新の速いツールでは、半年前に入れた例外が、今は不要・危険になっている可能性がある。定期的に機械で点検し、WARNを人間が判断する運用は、手間が小さく、効果が見込める。

限界も明確である。実際のClaude Codeの設定の構造や、組織の管理設定までは見ていない。また、スクリプトの判定基準は、筆者がChangelogから読み取った範囲に基づく。公式が推奨する設定とは限らない。

まとめ

Claude Codeの権限まわりの変更を踏まえ、設定ファイルを点検する小さなスクリプトを作った。スクリプトの動作はサンプルで確認したが、Claude Code本体での挙動は未検証である。点検結果のWARNは、保護を弱める設定を残す理由があるかを確認するきっかけとして使える。設定は書いたら終わりではなく、更新に合わせて見直すものとして扱いたい。

※本記事の記載内容は筆者個人の見解であり、所属する会社や組織の立場や方針とは一切関係ありません。

筆者情報

【Tomcat-zhou】|AI/AX/AIセキュリティ専門家

AI戦略洞察、AI駆動開発の方法論設計と現場で回る仕組みづくりをしています。
noteで戦略洞察 / Zenn・Qiitaで技術・方法論を書いています。
AIセキュリティ・AIコンサル・AIエージェント開発・AI活用・AI駆動開発教育、AI人材育成サービスを一体で提供。

X: @ZY20240528
LinkedIn: Tomcat-zhou
Facebook: zhou yi
note: Tomcat-zhou
Zenn: Tomcat-zhou

参考資料

  1. Claude Code Changelog(公式)
  2. AI Changelog Week 44(neomanex)

タグ

ClaudeCode AI Python セキュリティ AIエージェント

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?