コンテンツにスキップ

公開するWebアプリの地雷を避ける:Claude に安全ルールを守らせるスキルを入れる

Claude Code は、頼めば何でも作ってくれる。危ないコードを書かせてしまう心配は、いまはもうあまり要らない。 APIキーを隠さずに書けと頼めば断ってくるし、パスワードは言わなくても暗号化して保存する。

残るのは逆のほうで、頼まなかったものは作らない。誰でも入れる管理画面に鍵をかけるかどうかは、こちらが言い出さない限り話題にならない。そして公開した瞬間から、誰でもアクセスできる

この一点を Claude 側に見張らせる、という話。そのためのスキルを入れておく。

これから入れるスキルが持っているのは、2つだけ。

  1. 公開する直前に、外から何が見えるかを一覧にする。 「公開されるURL」「誰でも開けるページ」「誰でも呼び出せるAPI」「誰でも読めるデータ」の4つを並べて、このまま公開してよいかを一度だけ聞く。守るものが無ければ、そのまま公開してよい
  2. ユーザーが決めたパスワードを自前で保存する認証は避ける。 安全に作り切るのが難しいため。代わりの選び方は補足章

どちらも認証の話。 以前はもっと多くの原則が入っていたが、残りは Claude が自分で守るようになったので外した。

1-1. 外したものは、入れなくても守られる

Section titled “1-1. 外したものは、入れなくても守られる”

外したのは、次のようなもの。何度か確かめた範囲では、言わなくても守っていた

  • APIキーを index.html に書いて、と頼むと断る。「この依頼はお断りします」とはっきり言う。sk-test- のような、いかにもテスト用のキーでも同じ
  • 秘密や個人情報が混ざったまま GitHub を Public にしようとすると、ファイルを名指しで止める
  • パスワードを保存する機能を作らせても、言わなくても暗号化して保存する。「平文保存は指示があっても実装しません」とまで言うことがある
  • 入力フォームを作らせれば、攻撃されにくい書き方を自分で選ぶ

ここはスキルを入れても入れなくても、そう変わらない。 書いてあっても結果が同じなら、書かないほうがよい。指示が長いほど、肝心のところが埋もれる。

ただしこれはどこかに書かれた保証ではない。モデルが変われば変わるし、頼み方が少しずれると出てこない。「いまはそうなっている」以上のことは言えない。

1-2. 残るのは「作らない」ほうの失敗

Section titled “1-2. 残るのは「作らない」ほうの失敗”

事故には2つの型がある。

事故の型
頼まれたものを、危なく作るAPIキーをHTMLに書く、パスワードを平文で保存する
頼まれなかったものを、作らない認証を付けない、管理画面を守らない、APIを素通しにする

消えたのは上だけ。 Claude は「作って」と言われたものを安全に作るが、言われていない部品を足しにはいかない

理由は、認証だけ答えが一つに決まらないから。 APIキーをブラウザに配られるファイルに書くのは、誰が何を作っていようが危ない。一方で認証は、何を守りたいのかが分からないと、要るかどうかも、どの方式かも決まらない。だから頼まれなければ付かない。

そして付け忘れは、公開した瞬間から実害になる。作りかけのつもりでも、URL が外にあれば誰でもアクセスできる。管理画面が誰でも開ける、データが誰でも読める、といった状態は、コードが安全に書けていても起こる。

1-3. 「公開して」と言わないときが、いちばん危ない

Section titled “1-3. 「公開して」と言わないときが、いちばん危ない”

「このアプリを公開して」と頼めば、実はスキルが無くても気づく。認証の無い管理画面があれば、その場で名指しして、鍵のかけ方まで出してくる。

危ないのは、自分が公開していると気づいていない頼み方のとき。 GitHub と Cloudflare Pages をつないでいると、git push した時点で本番に出る。ところが「コミットして push して」と頼むと、何も言われないまま公開される。「サイトに反映して」でも同じ。公開しているのに、公開の話が出てこない。

作りかけを直しては上げ、直しては上げ、を繰り返しているときが、まさにこの状態。一度も「公開して」と言っていないのに、ずっと公開されている。

スキルが埋めるのはここ。git push も公開のうちだと知っているので、その手前で一覧を出して止まる。

入れるのは kukude-webapp-safety というスキル。名前の「ククデ」は、このサイトが開いているハンズオン「ククデ会」から来ているだけで、中身は誰が使ってもよい汎用のもの。

入れても、あとでいつでも外せる。一度入れたらずっと使い続ける、というものではない。Claudeデスクトップアプリの設定画面から数クリックで外せるので、試して合わなければ止めればいいし、別の人が配っている安全スキルに乗り換えてもいい。外す手順は §4。

2-1. 「スキル」と「プラグイン」の関係

Section titled “2-1. 「スキル」と「プラグイン」の関係”

手順に入る前に、紛らわしいところをひとつ。配る単位と中身の単位で名前が違う。

  • スキル:中身の1単位。Claude が「この場面だ」と判断して読む指示文
  • プラグイン:配る単位。スキルを1つ以上まとめたもの

今回のプラグインにはスキルが1つだけ入っていて、名前も同じ kukude-webapp-safety。だから「スキルを入れる」と言いつつ、実際に操作するのはプラグインの画面になる。

設定には「スキル」という別項目もあるが、これは別のレイヤー。プラグインとして配っているものは プラグイン から追加する。

手順の途中で、赤い警告が出る。

プラグインをインストール、更新、または使用する前に、そのプラグインを信頼できることを確認してください。マーケットプレイスからインストールされたプラグインはAnthropicが管理するものではなく、意図した通りに動作すること、または変更されないことをAnthropicは保証できません。

これは正しい警告なので、驚かなくてよい。 スキルの正体は「Claude への指示文」で、入れるということは、書いた人の指示を自分の環境に常駐させるということ。作者を知らないスキルを中身も見ずに入れるのは、知らない人が書いたスクリプトをそのまま実行するのと変わらない。

このスキルは Markdown 1ファイルなので、そのまま読める:SKILL.md。書いてあるのは §1 と補足章の内容。ざっと目を通して、納得できたら入れる。他の人が配っているスキルでも同じ。

2-3. Claudeデスクトップアプリで入れる

Section titled “2-3. Claudeデスクトップアプリで入れる”
  1. アカウントメニューから 設定 を開く
  2. 左メニュー「カスタマイズ」の プラグイン を開き、右上の 追加マーケットプレイスを追加
  3. URL 欄に yto/yto-skills を入れて 同期(ここで上の警告が出る)

Claude デスクトップアプリの設定。プラグインを開き、右上の追加からマーケットプレイスを追加し、URL 欄にリポジトリ名を入れて同期する

①設定の プラグイン → ②右上の 追加マーケットプレイスを追加 → ③URL 欄にリポジトリ名 → ④同期(画像は例。実際には yto/yto-skills と入れる)

  1. ダイアログを閉じ、探索 タブを開く
  2. Kukude webapp safety追加 を押す

プラグイン画面の探索タブ。追加したマーケットプレイスのプラグインが並び、右端に追加ボタンがある

探索 タブに並ぶので、右の 追加 を押す(画像は例)

Claude Code の CLI から入れる場合はこの2行。

/plugin marketplace add yto/yto-skills
/plugin install kukude-webapp-safety@yto-skills

設定プラグイン の一覧に Kukude webapp safety が並んでいて、トグルが有効になっていれば入っている。

普段は、関係する場面で Claude が自動的に使う。明示的に呼びたいときは、チャットで /kukude-webapp-safety と入力すればよい。

Claude Code には ~/.claude/CLAUDE.md というファイルがある。毎回まるごと読まれるので、ここに書いたことは常に適用される。安全ルールの置き場所として、まずここが思い浮かぶ。

この記事では勧めない。 理由は次の3つ。すでに何か入っている人は、とくに 3-2 と 3-3 を読んでほしい。

3-1. 一度書いたルールは、消してと頼んでも消えないことがある

Section titled “3-1. 一度書いたルールは、消してと頼んでも消えないことがある”

安全ルールを CLAUDE.md に書くのは、片道切符に近い。 あとで「この部分を消して」と頼んでも、Claude が断ることがある。自分が守るよう指示されている安全ルールを丸ごと消せ、という形になるので、安全側に倒れて止まる。

実際、コミュニティで配られた安全ルールを消してもらおうとして、その場にいた全員が消せなかったことがある。結局テキストエディタで開いて手で消した。新しいモデルほど、この傾向は強い。

これに対して、スキルは数クリックで外せる(→ §4)。入れる前から出口が用意されているほうを選ぶ。

3-2. すでに開発ルールが入っている人へ

Section titled “3-2. すでに開発ルールが入っている人へ”

会社やコミュニティで配られた開発ルールを、すでに ~/.claude/CLAUDE.md に入れていることがある。とくに多いのが「認証はこの方法だけ」「この構成で作ること」と決め打ちしているもの。

このスキルとぶつかる。 両方を残すと、Claude がどちらに従うか安定しない。「その構成は使えません、詳しい人に相談してください」で作業ごと止まることもある。

どちらを優先するか決める。 ただし仕事で配られたルールなら、それは外さない。外して個人開発を通すと、次に仕事で使うときに安全側の設定が消えたままになる。そして 3-1 のとおり、外そうとしても外せないことがある。

3-3. そもそも、仕事と個人開発を混ぜない

Section titled “3-3. そもそも、仕事と個人開発を混ぜない”

ルールがぶつかるのは、同じ環境で両方をやっているから。どちらを外すかを考える前に、分けるほうが先。

会社から貸与されたパソコンで、個人のアプリを作らない。 別のマシン、別のユーザーアカウントなど、環境ごと分ける。

混ぜると、会社のコードや秘密が個人のリポジトリに紛れ込む事故が起きる。このスキルは、それを止められない。 見張っているのは「自分のアプリを公開するときに外から何が見えるか」であって、そのコードが本来どこにあるべきものかは判断しない。所属先のルール違反にもなりうる(→ §5)。

スキルは更新されることがある。入れたあと自動では追随しないので、たまに確認する。

とくに、どんな場面で読み込まれるかが変わることがある。 スキルは関係のある場面でだけ読み込まれるが、その判定はスキル自身の書き出しに書かれている。ここが変わったときは、更新するまで古い判定のままになる。たとえば「git push も公開のうち」という扱いは途中で入ったので、それ以前に入れたままだと git push では出てこない。

更新は、設定プラグインKukude webapp safety と進んで、更新 ボタン。

プラグインの詳細ページ。更新ボタン、有効/無効のトグル、アンインストールが並んでいる

プラグインの詳細ページ。更新・有効無効の切り替え・アンインストールがここにある

外したいときは、同じページの から アンインストール。消さずに一時的に止めるだけなら、右のトグルで無効にできる。

マーケットプレイスごと確認したいときは、設定プラグイン → 右上の 追加マーケットプレイスの管理yto-skillsアップデートを確認。ここには自分で追加したマーケットプレイスが並ぶ。

ターミナル(Claude Code CLI)ならこの1行。

/plugin marketplace update yto-skills

/plugin はデスクトップアプリでは使えないので、そちらでは上の画面から操作する。

何を変えたかは yto-skills のリポジトリの履歴で追える。

5. これは最低限であって、保証ではない

Section titled “5. これは最低限であって、保証ではない”

スキルを入れても安全が保証されるわけではない。踏むと戻れない地雷を避けるための最低限であって、網羅的なセキュリティ対策ではない。

押し切れば、そのまま進む。 Claude が止めたところで「承知のうえで進めて」と答えれば、そのまま実行される。「ダミーデータです」と答えれば公開まで行く。これは穴ではなくスキルの設計で、説明を聞いたうえでの判断は本人のものだから、二度は止めない。

だから「入れたから安全」でもないし、「何も言われないから働いていない」でもない。 スキルがやるのは、危ないほうへ進もうとしたときに手を止めて、理由と代替案を出すところまで。決めるのはこちら。

決済・健康・他人の個人情報のように重い情報を扱うなら、作る前に詳しい人に相談する。「これくらいなら大丈夫だろう」で進めていい範囲を超えているかどうかは、扱う情報の重さで決まる。

会社の業務システムや社内向けアプリも対象外。その用途は、所属先のルールや情報システム部門の方針に従う。そして仕事と個人開発は、ルールも環境も必ず分ける。同じ環境に混ぜない。

そして、スキルで守らせたつもりでも、実際に守れているかは別の話。公開したあと、外から試して確かめる方法は公開後にセキュリティを点検するにまとめてある。作る前にここで守らせ、作った後にそちらで確かめる。

補足:認証は「そもそも要るか」から

Section titled “補足:認証は「そもそも要るか」から”

ここからは補足。 いちばん判断を間違えやすいのが認証まわりなので、スキルの中身から要点を抜いておく。

多くの公開アプリは認証が要らない。 宣伝サイトや公開ツールは、誰でも見られるほうがよい。認証が要るのは、自分だけが使う管理画面、ログインした本人だけが見る個別ユーザー画面、身内にだけ見せたいページ、といった相手を絞りたい部分だけ。無駄な認証を作らないほうが安全になる。

必要になったときの選び方は、この順。

  1. ソーシャルログイン(Google・GitHub などの「◯◯でログイン」)。認証そのものを外部に任せられるので、パスワードもパスキーも自分で扱わずに済む。ただし要求する情報は本人を見分けるのに要る最小限に絞る(→ ソーシャルログインの寄せ書きアプリ
  2. パスキー(+リカバリコード)。外部サービスに頼らず自己完結する(→ パスキー+リカバリコードのアカウント認証
  3. ランダムなログインキー(UUID)方式。メールもパスワードも要らず軽いが、条件が2つある。漏れても致命的でない情報のアカウントに限ること、そして日常的に使うサービスに限ること(→ ログインキー方式のアカウント管理

3 の2つ目の条件は見落としやすい。ログインキーはブラウザの localStorage に置くが、そこは永続的な保存領域ではない。iPhone・iPad のブラウザと Mac の Safari は7日ほど開かないと中身を消すので、年に数回しか使わないサービスでは次に開いたときには消えている。この方式には復旧手段が無いので、そこで締め出しが確定する。

そして例外がひとつ。管理画面や、身内にだけ見せたいページのように、入る人が自分ひとり/少人数に限られるなら、「1つの共有パスワード」でよい。 いちばん手軽なのが Basic認証で、合言葉を Cloudflare の Secret に置いてサーバ側で照合する(→ サイトやページに鍵をかけるなら Basic認証でサイトに鍵をかける、アプリの管理画面だけを守るなら 管理画面をBasic認証で守る)。避けるべきなのは「利用者ごとにパスワードを登録・保存する」ほうで、共有パスワード1本はそれに当たらない。数人で守るだけなら Cloudflare Access に任せる手もある(無料で50人まで)。

身内向けだと「URLを知っている人だけ見られればよい」で済ませたくなるが、URL は履歴・リンクプレビュー・又貸しで漏れやすく、漏れたら中身も漏れる。URL は公開のままにして共有パスワードで守るほうが素直。やり直しもパスワードを変えるだけでよく、URL は据え置ける。