使わない機能を切るのが、最も重要なセキュリティ対策 | Claudeで見つけよう

コードを読まないAIエンジニア
サムネイル

自分で書いた最小の設定ファイルのまま、サービスを動かしていませんか? この記事では、使っていないのに外から届く機能をClaude Codeに洗い出させる依頼文を載せます。言語を問わず、Claude Codeで開けるリポジトリならそのまま貼れます。試しにOSSのHTTPプロキシのtinyproxyに流すと、7分で24項目が返ってきました。そのうち2件は、アクセス制限を書かないと誰からでも中継を受け付け、接続先のポート制限を書かないとどのポートにもつながる、という警告なしの初期設定で、どちらも設定を2行足せば閉じます。

元になったのは、Anthropicが2026年10月20日に公開した研究です。脆弱性を1件ずつ直すより、使わない機能を切って攻撃対象領域(アタックサーフェス)を減らすほうが、未知の脆弱性までまとめてリスクを下げられる、という立場です。研究自身は、開発者が目に見える形で安全性を上げる、最も実用的な方法のひとつと書いています。私は、セキュリティ対策で最初に手を付けるならここだと考えています。依頼文は、研究の3つの観点(初期設定のまま外から届く機能、設定どうしが打ち消し合って黙って外れる防御、ログインする前に誰でも動かせるコード)をもとにしています。

使わない機能を切ると、なぜ安全になるのか?

頑丈な玄関の鍵より、使っていない勝手口を閉じるほうが効くことを示す図

鍵を強くするより、勝手口を閉じる

玄関の鍵をいくら頑丈にしても、使っていない勝手口が開いていたらどうでしょう?泥棒は勝手口から入ります。勝手口を閉じれば、そこの鍵が弱いかを心配する必要もなくなります。

コードも同じで、外から届くコードを減らせば、そこに潜む未発見の脆弱性は攻撃に使えなくなります。研究を書いたのはFrontier Red TeamのChris Rohlfさんで、Claudeに次の3つの観点でコードを読ませています。

  • デフォルトの設定のまま外から届く、意図していないコード
  • 設定の組み合わせで、警告もなく無効になる防御
  • ログイン(認証)より前など、早い段階で動く扱いに注意が要るコード

25のOSSで見つかった493件の問題

対象は25のOSS、C、C++、Java、PHP、Pythonの500万行以上で、見つかった問題は493件でした。コードを1行ずつ読むだけでは見えない問題が、これだけ眠っていたことになります。

目立つのは設定の組み合わせの問題で、162件ありました。うち94件は防御が黙って無効になるもの、68件は防御どうしの食い違いです。設定を1項目ずつ正しく書いたつもりでも、組み合わせると防御が消えるわけです。

無関係な4つのプロジェクトで、同じ落とし穴が見つかっています。逆引きDNSを有効にしないままアクセス制限をホスト名で書くと、拒否ルールが一度も働かず許可の側に倒れる(fail-open)というものです。

別件として、21年間残っていた例もあります。クライアント証明書を必須にする設定を、別の設定が実質的に無効にしていました。どちらも、設定を1行ずつ読んでも気づけません。

OpenSSHは、ログイン前に動くコードを減らした

ログイン前に届くML-DSA-44(耐量子の署名方式)のコードは約4,500行あり、OpenSSH自身のログイン前コードの約16%を占めていました。

8月11日の10.5では、相手から送られた鍵を解析する前に、許可した方式かどうかを確かめるよう順番を変え、10月6日の10.6では、鍵とCA署名の種類の確認をさらに前に出しました。研究では、この一連の修正で約2割減ったと説明しています。ログインする前の、誰でも触れる入口で動くコードが、それだけ減ったということです。リリースノートには「Chris Rohlf in collaboration with Claude and Anthropic Research」という謝辞があります。

では、この考え方を自分のリポジトリに向けるには、Claudeへどう頼めばいいのでしょうか。

使わない機能をClaudeに見つけさせる依頼文

研究の手法は1つのClaude Skillにまとめられています。研究はOSS-Scannerに組み込む作業中と書いており、単体で配られているSkillは見つけられませんでした。そこで3観点をもとに、私が依頼文に起こしました。Claude Codeで調べたいリポジトリを開いて、貼るだけで始められます。

そのまま貼れる依頼文

このリポジトリの「攻撃対象領域」を洗い出してください。個々の脆弱性を探すのではなく、「外から届くのに、届かなくてよいコード」と「設定次第で黙って外れる防御」を見つけるのが目的です。コードは変更せず、読むだけにしてください。

最初に前提を1段落でまとめてください。このソフトは誰が使う想定か(不特定多数/認証した利用者/社内だけ)、外部からの入力が最初に入る場所(ファイルと関数)、設定ファイルを読み込む場所と、各設定のデフォルト値が決まる場所です。

次の3つの観点で、順に調べてください。

1. デフォルト設定のまま届くコード
設定を何も書き換えずに起動したとき、外部からの入力で実行されるコードのうち、多くの利用者には要らない機能(古いプロトコル、デバッグ用、オプションの機能)を挙げてください。そのデフォルト値がどこで決まっているかを、ファイルと行で示してください。

2. 設定の組み合わせで黙って外れる防御
アクセス制限・認証・暗号化・上限値など、セキュリティに関わる設定を先に一覧にしてください。そのうえで、2つ以上の設定を組み合わせたときに、片方の防御が警告もなく効かなくなる組み合わせを探してください。特に、拒否のルールが「判定できないときに許可の側へ倒れる」(fail-open)箇所を見てください。

3. 認証より前に動くコード
認証やアクセス制限の判定が終わる前に、外部からの入力で実行される処理(解析、名前解決、ログ出力、メモリ確保など)を挙げてください。その処理を判定の後ろへ回せないかも書いてください。

報告の書き方:
- 1件ごとに「どの設定のとき」「外部から何を送ると」「どのコード(ファイル:行)に届くか」「何が起きうるか」「直し方の案(デフォルトを変える/チェックを前に移す/起動時に警告を出す)」を書く
- コードで確かめた事実と推測を分けて書く。確かめていないものには「未確認」と付ける
- 最後に、影響の大きい順に上位5件を表にする

事実と推測を分けさせる理由

Claudeの指摘には、コードで確かめた事実と推測が混ざります。ラベルがあれば、どこから動かして確かめるか決められます。

前提の段落を最初に書かせるのは、既定値がどこで決まるかを押さえないと、同梱のサンプル設定の値を「デフォルト」と取り違えるからです。試したときも、Claudeは「コードの既定値」と「同梱サンプル設定の値」を自分から分けて書いていて、この区別が次の結果に効いてきます。

Claudeで小さなプロキシを調べると、何が見つかったか?

tinyproxyの設定がPortだけのときと、AllowとConnectPortの2行を足したときの違いを示す図

7分で24項目、ファイルと行番号つき

依頼文を流した相手は、OSSのHTTPプロキシのtinyproxyです。C言語で約1万行と小さく、全体を読ませやすいので選びました。

Claude Codeのサブエージェントに依頼文と対象フォルダだけを渡し、読むだけでコマンドは実行させていません。かかったのは7分24秒、ツール呼び出し35回、約22.6万トークンでした。

返ってきたのは24項目で、観点1が8、観点2が11、観点3が5です。観点1のうち1件は、デバッグ用のコードについて「確認した結果、既定では届かない」と自分で打ち消していました。各項目にファイルと行番号、「事実/推測/未確認」のラベルが付き、指摘の場所はすぐ開けます。

動かして確かめたのは、そのうちの2件だけです。残り22件は確かめていません。設定の書き方に関するものや、認証前の処理に関するものが含まれます。

上位2件は、知らないと開いたままの初期設定

2件は、使い捨てのコンテナで動かして確かめました。通信先はコンテナ自身のlocalhostだけです。

1件目は、AllowもDenyも書かず Port 8888 だけの設定で起動したケースです。tinyproxyは0.0.0.0と[::]の全インターフェースで待ち受け、プロキシ経由の中継もできました。起動ログの警告は「You SHOULD set a UserName」の1行だけで、Allowがないことへの警告は出ていません。警告なしに、開いたままでした。2件目はConnectPortを書かないケースで、CONNECTが任意のポートに通りました。試したのは6000番です。

どちらも公式ドキュメントに書かれた仕様で、"If there are no Allow or Deny lines, then all clients are allowed." と "If no ConnectPort line is found, then all ports are allowed." の2文がそれにあたります。新しい脆弱性ではなく、最小の設定で動かすと開いたままになる初期設定なんです。

最小の設定ファイルを自分で書いて動かすと、ここにはまります。同梱のサンプル設定には Allow 127.0.0.1 が入っていますが、ConnectPortの行はコメントアウトされています。サンプルから始めてもConnectPortは開いたままで、Port だけの設定を自分で書けばAllowも外れます。

設定を2行足せば閉じる

直し方は、設定に2行足すだけです。

Port 8888
# 足した2行
Allow 127.0.0.1
ConnectPort 443

ConnectPort 443 を足すと、同じ6000番へのCONNECTはログにこう出て拒否されました。

Refused CONNECT method on port 6000

Allowも、1行書けば書いた相手以外は拒否されます。試しに Allow 10.0.0.1 だけを書いて手元から頼むと、403が返り、ログには Unauthorized connection from "127.0.0.1". と出ました。

Claude Codeのsecurity-reviewとの使い分け

security-reviewは変更差分を、今回の依頼文はリポジトリ全体を見るという範囲の違いを示す図

/security-review は、今のブランチとデフォルトブランチの差分を読み、インジェクションや認証の不備などを探すコマンドです。今回の依頼文はリポジトリ全体を対象に、届かなくてよいコードと黙って外れる防御を探します。

では、いつどちらを流すか?私は、/security-review はプルリクエストのたびに、依頼文は外に公開する前と、設定項目の多い機能を足したときに流すのがいいと考えています。差分のレビューは新しく開けた穴を、全体の洗い出しは前から開いたままの勝手口を見つける分担です。

Claudeの洗い出しを使う前の注意

指摘には推測が混ざります。今回動かして確かめたのは2件だけで、依頼文を流したのも1回です。設定を変える前に、手元の環境で動かして確かめてください。

自分が管理していないOSSで、まだ報告されていない不具合らしきものが出てきたら?SNSやブログで公開せず、そのプロジェクトのSECURITY.mdなどに書かれたセキュリティ窓口へ報告します。

トークンもかなり使います。約1万行のtinyproxyで約22.6万トークンだったので、大きなリポジトリならディレクトリを絞って流すほうが現実的です。また、依頼文は研究のSkillそのものではないので、研究と同じ精度で見つかるとは限りません。

最初に流すなら、自分で設定ファイルを書いて外に公開しているサービスから始めてください。依頼文はコードを読むだけで、変更はしません。貼って候補が並んだら、その中から1件、設定で閉じるところまでやってみてください。

tinyproxyで閉じたのは、たった2行でした。あなたのリポジトリの勝手口にも、同じように1行で閉じられるものがあるかもしれません。