Claude Media
Claude Code SQLと正規表現を安全に書かせる勘所

Claude Code SQLと正規表現を安全に書かせる勘所

Claude CodeにSQLや正規表現を書かせる実務ポイントをまとめます。MCP接続とBash直接実行の使い分け、生成SQLの検証手順、ripgrep構文とアプリコードの正規表現の違いを扱います。

Claude CodeにSQLや正規表現を書かせるとき、コードを書かせるときとは違う注意点が1つ増えます。生成した文字列がその場で実行される経路が複数あり、経路ごとに検証すべきポイントが違う点です。SQLならMCP接続かBash直接実行か、正規表現ならClaude Code自身のGrepツール向けかアプリコード向けかで、書き方も安全策も変わります。本稿はこの2つを軸に、実行前に何を確認すればよいかを扱います。

Claude CodeにSQLと正規表現を書かせると何が起きるか

Claude CodeはSQLも正規表現も、他のコードと同じように自然文の指示から生成します。違うのは実行経路が3つに分かれる点です。データベースへのSQLはMCPサーバー経由かBashでのクライアント直接実行のいずれかで走ります。正規表現はClaude Code自身のGrepツールに渡すか、生成したコードの一部としてアプリケーション側の正規表現エンジンに渡るかで先が分かれます。

この3経路を区別せずに「SQLを書かせる」「正規表現を書かせる」とだけ考えると、検証すべき箇所を見落とします。以降の節では、SQLの2経路(MCP接続とBash直接実行)、そして正規表現の2文脈(Grepツールとアプリコード)を順に見ていきます。

データベースへのSQLはMCP接続かBash直接実行かで検証ポイントが変わる

Claude Code公式ドキュメントは、MCPサーバー経由でのデータベース接続を自然文の例で紹介しています。「PostgreSQLデータベースを使い、機能ENG-4521を使ったユーザー10人のメールアドレスを探して」といった具合です。実在するMCPサーバーの1つがDBHub(@bytebase/dbhub)で、接続文字列を渡すだけでPostgreSQL・MySQL・SQLiteなどに接続できます。

claude mcp add --transport stdio db -- npx -y @bytebase/dbhub \
  --dsn "postgresql://readonly:pass@prod.db.com:5432/analytics"

接続文字列に読み取り専用ユーザーを使う設計や、/mcpでの接続確認、認証まわりの詳細はClaude CodeでMCPからデータベースに接続する方法に譲ります。本稿で押さえたいのは、もう1つの経路であるBash直接実行との違いです。

経路検証すべきポイント向くケース
MCP接続(DBHub等)検証すべきポイント接続時点のDB権限(読み取り専用ユーザーか)向くケース定常的な集計・スキーマ探索
Bash直接実行(psql -c等)検証すべきポイントコマンドごとの権限ルール設計向くケース1回限りの調査、MCPサーバー未導入の環境

Bash直接実行を選ぶ場合、psqlmysqlはClaude Codeの組み込み読み取り専用コマンド一覧には入っていません。この一覧はlscatechopwdheadtailgrepfindwcwhichdiffstatducdと、読み取り専用形式のgitに限られ、設定で追加はできません。DBクライアントは含まれないため、素のBash askルールのままなら実行のたびに権限確認が発生します。ただしsandbox機能を有効にし、既定でtrueのautoAllowBashIfSandboxedをそのままにしている環境では話が変わります。sandbox化されたBashコマンドはこのask確認自体をスキップして実行されるため、「DBクライアントは常に確認が挟まる」とは言い切れません。

ここでBash(psql -c *)のような許可ルールを書いて確認を省略したくなりますが、公式ドキュメントは引数を制限するBashルールの脆さを明確に警告しています。curl http://github.com/*という一見安全なルールが、オプションの位置やリダイレクト、変数展開で簡単にすり抜けられる例が挙げられています。同じ弱点はpsql -cのようなSQL実行コマンドにもそのまま当てはまります。文字列一致のルールだけでSQLの安全性を担保しようとしないことが要点です。公式ドキュメントが示す防御は段階的で、脆い許可ルールの次にPreToolUseフックによる内容検査があり、さらにOSレベルで全プロセスの動作を止めたいならsandboxの有効化が案内されています。

Pro・Max・Teamの各プランでは、確認を毎回出す「Manual mode」に対し、「Auto mode(自動判断モード)」では分類器がほとんどの確認を代行し、人手の承認を省略します。DBクライアントのように組み込みの読み取り専用一覧に入らないコマンドは、Auto modeでも分類器の判断1つに委ねる形になります。書き込み系のSQLを流す環境では、権限ルールやフックによる明示的なガードを外さない判断が要ります。

より確実に止めたいなら、PreToolUseフックでBashコマンドの中身を検査する方法があります。公式ドキュメントには、rm -rfを含むコマンドをスクリプトでチェックし、該当すれば終了コード2でツール呼び出しそのものを拒否する例があります。同じ仕組みは、コマンド文字列にDROP TABLEDELETE FROM(WHERE句なし)のようなパターンが含まれるときに拒否する用途にも応用できます。ルールベースの許可リストより、実行直前の内容検査のほうがSQLの事故防止には向いています。フックの設定項目とイベントの全体像はClaude Code Hooks完全ガイドにまとめてあります。

権限ルールとフックはどちらも.claude/settings.jsonに書きます。チームで共有するpermissions.allow/ask/denyとHooksの設定項目は、個人用のsettings.local.jsonと役割が分かれます。使い分けはClaude Code settings.json完全ガイドが詳しいです。

そもそもSQLをその場で実行させる必要があるか

MCP接続もBash直接実行も、Claudeが書いたSQLをその場でデータベースに投げる経路です。もう1つ、リスクの質が変わる選択肢があります。SQLをその場で実行させず、マイグレーションファイルや分析用クエリとして.sqlファイルに書かせ、通常のコードと同じくプルリクエストでレビューしてから流す方法です。

この場合、危険なのは実行時の権限ではなく、レビューを飛ばして反映してしまう運用の緩さのほうに移ります。スキーマ変更を伴うマイグレーションや行数の大きいバッチ更新は、対話セッションでその場で実行させるのに向きません。いったんファイルに書き出して人間のレビューを挟むほうが、Bashの権限設計やフックだけに頼るより事故を防げます。定常的な集計クエリはMCP接続、1回限りの重い変更はファイル化してレビューを挟む、という使い分けが実務では効きます。

生成されたSQLを実行前にどう確認するか

権限設計を固めても、Claudeが書いたSQL自体の正しさは別問題です。生成AIが書くSQLでありがちなつまずきは、次のようなものです。

  • UPDATEDELETEWHERE句が付いているか(全件更新・全件削除の事故)
  • JOINで行が重複し、集計値が水増しされていないか
  • LIMITなしのSELECT *で想定より大きい結果セットを返していないか
  • 日付範囲の境界(<<=か)が意図通りか

実行前にはまずEXPLAINで実行計画を確認し、更新系のクエリは本番実行の前にトランザクションで囲んでロールバックする手順が有効です。集計クエリなら、まず件数だけを数えるクエリを走らせてから本クエリに進むと、想定外の行数に早い段階で気づけます。Claude自身にクエリの意図を説明させ、それが自分の要求と一致しているかを読んでから実行に移すという一手間も、実行後に気づくより安く済みます。

正規表現はGrepツール用とアプリコード用で構文が変わる

正規表現には、SQLとは別の落とし穴があります。Claude Code自身が使うGrepツールはripgrepを基盤にしており、ripgrepの正規表現構文を使うため、通常のPOSIX grepとは書き方が変わります。公式ドキュメントの例では、Goコードのinterface{}を検索する場合、interface\{\}のように波括弧をエスケープする必要があると説明されています。

この区別が重要な理由があります。コードベース内を検索させる目的で書いた正規表現と、バリデーションやログ抽出のコードに埋め込む正規表現は、同じ「正規表現を書いて」という指示から生まれても前提が違うからです。前者はripgrepの構文で、Claude Code自身のGrepツールに直接渡せる形である必要があります。後者はアプリケーションの実行言語(JavaScript、Python、Javaなど)の正規表現エンジンが解釈できる構文である必要があり、両者は必ずしも互換ではありません。

依頼するときは「この正規表現はコードを検索するためのものか、アプリケーションに組み込むものか」を最初に伝えると、Claudeが前提とする構文がぶれません。検索用の正規表現ができたら、実際にGrepツールへ渡して手元のファイルに対して試し撃ちできる点もClaude Codeならではの利点です。パターンやファイルタイプがripgrepに拒否されたときは、ripgrep由来の診断メッセージがそのまま返るため、Claudeはその場でパターンを修正して再検索できます。

Grepツールで正規表現を試し撃ちするときの注意点

Grepツールにはfiles_with_matches(ファイルパスのみ、既定)・content(マッチ行と行番号)・count(件数)という3つの出力モードがあります。パターンの精度を見たいならcontentモードを明示的に指定させます。もう1つ見落としやすいのが行の境界です。Grepツールは既定で1行内だけをマッチ対象にします。複数行にまたがるパターンを試したい場合はmultiline: trueを明示しないと、実際には一致するはずの箇所が「マッチなし」と誤判定されます。

アプリコード側の正規表現でも、テスト観点は共通しています。貪欲マッチ(.*)と非貪欲マッチ(.*?)の取り違えで意図より広い範囲を拾っていないか。ユーザー入力をそのままパターンに埋め込んで、壊滅的バックトラッキング(catastrophic backtracking、入力長に対して指数的に処理時間が伸びるReDoSの原因)を起こす構造になっていないか。Claudeが書いた正規表現でも、人が書いたものと同じようにこの2点の確認が要ります。空文字列・改行を含む文字列・想定より長い入力の3種類をテストケースとして渡し、期待通りにマッチ/非マッチになるかを確認してから組み込むのが手堅い進め方です。

まとめ

Claude CodeにSQLと正規表現を書かせるとき、確認すべき場所は生成物そのものだけではありません。SQLはMCP接続かBash直接実行かで権限設計の当てどころが変わり、正規表現はGrepツール向けかアプリコード向けかで構文の前提が変わります。実行経路を先に決めてから依頼すると、生成されたクエリやパターンをどう検証すればよいかが自然に絞り込めます。

この記事を共有:XはてブLinkedIn