CursorやClaude Codeのような開発支援ツールを使えば、WebアプリやAPIサーバが驚くほど手軽に作れるようになりました。「ログイン機能を作って」「データベースからユーザー情報を取得して」「このAPIをサーバに公開して」と頼めば、短時間でそれらしく動くものが完成します。
APIキーやデータベースの接続情報を、ブラウザ側ではなくサーバ側の環境変数に保存しておけば安全、という説明も広まりました。これは正しい対策です。仕組みはAPIキーをクライアント側に書いてはいけない理由や環境変数の扱いで整理しています。
ただし、秘密情報をサーバに移しただけで、アプリ全体が安全になるわけではありません。この記事では、認証と認可の違いを入り口に、AIで作ったWebアプリを公開するときに確認したいサーバ側の安全性を、全体として整理します。
結論:サーバ側に置いただけでは安全にならない
先に結論です。APIキーや機密情報をサーバ側に保管するのは重要ですが、それはセキュリティ対策の一部にすぎません。
たとえば、APIキー自体はブラウザから見えない場所にあっても、誰でも呼び出せるAPIが用意されていれば、そのAPIを経由して機能を勝手に使われることがあります。ユーザー情報を返すAPIにログイン確認がなければ、外部から直接データを取得されるかもしれません。ログイン確認があっても、他人のIDを指定するだけで情報が取れるなら、やはり安全とは言えません。
サーバを安全にするには、少なくとも次の観点が必要です。
- アクセスしている人を確認する(認証)
- その人が操作できる範囲を確認する(認可)
- 外部に公開する範囲を絞る
- 入力されるデータを信用しすぎない
- 機密情報を画面やログに出さない
- 異常な利用を検知・制限する
まず、最初の2つ、認証と認可から見ていきます。
認証とは:アクセスしている人を確かめる
認証は、アクセスしている人が誰なのかを確認することです。建物でたとえるなら、受付で身分証を提示して本人だと確かめる段階です。
Webアプリのログインでは、メールアドレスとパスワード、ワンタイムパスワード、認証アプリ、生体認証などで本人を確認します。ログインの内部の流れはログインの仕組みで解説しています。認証に成功すると、サーバは「このリクエストの送り主はユーザーAだ」と判断できます。ただし、ログインできたからといって、アプリ内のすべてを見せてよいわけではありません。そこで認可が要ります。
認可とは:その人が操作できる範囲を決める
認可は、認証された人が、どのデータや機能を使ってよいかを判断することです。会社に入館できた人でも、すべての部屋に入れるわけではありません。一般社員が入れる部屋、経理だけの部屋、管理者だけの部屋がある。社員証をかざしてドアが開くかどうかを決める仕組みが、認可に近いものです。
Webアプリでも、一般ユーザーは自分の情報だけ、店舗担当者は自分の店舗の注文だけ、管理者はすべてを管理できる、というように、誰が何をできるかを決めます。
認証と認可は似た言葉ですが、役割は別です。認証は「あなたは誰ですか」、認可は「あなたはこれをしてよいですか」。両方がそろって、はじめて適切なアクセス管理になります。
ログイン機能があっても、安全とは限らない
AIに「会員向けのプロフィール画面を作って」と頼み、ログインした人だけがプロフィールに進める作りができたとします。一見、安全そうです。
ところが、プロフィールを取得するAPIが /api/users/123 のように、末尾の番号(利用者ID)でデータを返す作りで、サーバが「ログインしているか」だけを見て中身を返していたら、その番号を /api/users/124 に書き換えるだけで、別のユーザーの情報が返ってくるかもしれません。
この場合、認証はあります(ログインしない人は使えない)。しかし、「ログイン中の人が124番を見てよいか」という認可の確認がありません。必要なのは、データを返す前に「取得しようとしているデータの持ち主 = いまログインしている本人か」を確かめることです。管理者だけが他人の情報を見られる設計なら、管理者権限の確認も要ります。
こうした、IDを書き換えて他人のデータに届いてしまう問題は、IDORやBOLAと呼ばれることがあります。用語を覚える必要はありません。大事なのは、ログインできるかどうかと、対象データを操作してよいかどうかは、別々に確認するという点です。
画面で隠しても、サーバが許可していれば操作できる
管理者以外にボタンを表示しない、未ログインではページを開かせない、といった画面側の制御は、使いやすさのために必要です。ただし、これだけではセキュリティ対策になりません。ブラウザに表示される画面と、データを処理するサーバは別物だからです。
攻撃者は、画面のボタンを押す必要はありません。APIのURLが分かれば、開発者ツールや専用ソフト、プログラムから直接リクエストできます。画面で管理ボタンを隠しても、サーバ側の管理者APIが誰でも実行できるなら、直接呼ばれてしまいます。
だから、重要な確認は必ずサーバ側で行います。サーバは、リクエストを受け取ったら「ログインしているか → 誰か → 対象データを操作してよいか → 送信データに問題がないか」を確認してから処理します。画面側の制御は補助で、最終的に許可を決めるのはサーバです。
AIで作ったサーバで確認したい代表的な穴
認証・認可以外にも、公開前に見ておきたい点があります。
1. 必要のないAPIやデバッグ機能が公開されている。 開発中に作った、データ一覧表示、テストユーザー作成、初期化、管理者権限付与、デバッグ情報表示などのAPIが、本番でも外部から呼べる状態だと大事故になります。画面からリンクしていなくても、URLは推測・探索されます。使わないものは消すか、外部から触れないようにします。
2. 受け取った入力をそのまま信用している。 画面で金額を変えられなくても、APIへ直接送る値は書き換えられます。購入処理で価格を利用者側から受け取り、それをそのまま信用すると、価格を1円に書き換えて注文されるかもしれません。価格は商品IDをもとにサーバ側で取り直します。ユーザーID・管理者かどうか・会員プラン・割引率・支払い済みか、なども利用者から来た値を信用してはいけません。
3. 入力がデータベースや画面にそのまま渡される。 受け取った入力を、そのままデータベースへの命令やHTMLとして使うと、意図しない処理を実行される恐れがあります。代表例がSQLインジェクション、クロスサイトスクリプティング(XSS)、表計算に混入する数式インジェクションです。最近のフレームワークには安全な仕組みがありますが、AIが生成したコードが常に正しく使うとは限らないため、文字列を直接つないでSQLを作っていないかなどを確認します。
4. APIキーは隠れていても、機能を使い放題になっている。 外部AIのAPIキーをサーバに置くのは正しくても、/api/generate のようなAPIを誰でも呼べるなら、キーを盗まれなくても第三者があなたのサーバ経由でAIを大量に使えます。結果、想定外の料金が発生します。実際に起きるサーバレスの高額請求と同じ構図です。ログイン済みだけに限定する、回数を制限する、利用量を記録する、上限を設ける、といった対策が要ります。
5. エラー画面やログに機密情報が出ている。 本番で詳細なエラーを表示すると、テーブル名、ファイルパス、SQL、環境変数、APIキーなどが漏れることがあります。画面に出さなくても、ログにそのまま書いているケースもあります。本番では利用者に最低限のエラーだけを返し、調査用の情報はアクセスを制限したログへ。そのログにもパスワードやキーを記録しません。
6. アクセス回数に制限がない。 ログイン、パスワード再設定、認証コード送信、AIによる生成などに回数制限がないと、大量試行や悪用を受けます。ログインを何度でも試せればパスワードを総当たりされ、メール送信を何度でも呼べれば大量送信に使われます。IPやユーザーごとの回数制限、一定回数の失敗での一時停止、1日あたりの上限、不自然なパターンの検知を設けます。認証があるから安全とは限らず、正規アカウントを取ったうえで悪用されることもあります。
CORSやHTTPSは、それだけでは守りにならない
Webアプリを作っていると、CORSという設定を目にします。これは、ブラウザ上のページが別ドメインのサーバへアクセスできる範囲を制御する仕組みで、認証や認可の代わりにはなりません。特定サイトだけを許可していても、ブラウザ以外のプログラムからAPIへ直接アクセスされる可能性があります。「自分のサイトからしか来ないからログイン確認は不要」という考えは危険です。CORSの役割はCORSエラーの記事で整理しています。
HTTPSも同様です。通信経路を暗号化する必須の対策ですが、守るのは経路だけ。認証がない、認可が抜けている、他人の情報を返している、といったサーバ側の問題は、HTTPSでは防げません。鍵マークが出ていることと、アプリ全体が安全であることは別です。
サーバやデータベースの公開範囲も確認する
コードだけでなく、サーバやネットワークの設定も重要です。Webサーバは外部に公開しますが、すべてを公開する必要はありません。とくに、データベースへ外部から直接接続できる状態は通常不要です。データベースは、アプリケーションサーバなど必要な場所からだけ接続できるようにします(この考え方はAIに任せるデータベースの安全にも通じます)。
あわせて、必要のないポートが開いていないか、管理画面へ誰でも入れないか、初期パスワードのままでないか、開発環境と本番環境が分かれているか、本番データを開発へそのままコピーしていないかを確認します。また、公開後にライブラリやフレームワークへ脆弱性が見つかることもあるため、外部部品を通じた攻撃に備え、何を使っているかを把握し、更新できる状態を保ちます。
AIに実装を頼む前に、人が決めておくこと
「ログイン機能を作って」だけでは、必要な条件が伝わりません。まず人間側で、ログインせず使える機能、一般ユーザーが使える機能、管理者だけの機能、見てよいデータの範囲、会社や店舗ごとに分けるか、更新・削除をできる人、重要操作で再確認するか、を決めます。
そのうえで、たとえば注文APIなら「ログインしていない人は使えない/一般ユーザーは自分の注文だけ取得できる/URLの注文IDを書き換えても他人の注文は取れない/管理者は全注文を取得できる/権限確認は画面側でなくAPI側で行う/更新と削除にも同じ認可を適用する」と、条件を具体的に伝えます。条件が細かいほど、AIが実装すべきことも明確になります。ただし、詳しく指示しても実装が完全に正しいとは限らないため、出てきたコードや動作を確認する工程は残ります。
AIにセキュリティを確認させるときの観点
生成したコードは、AIにレビューさせることもできます。「未ログインで呼べる重要APIはないか/一般ユーザーが他人のデータを取得・更新・削除できないか/管理者向け機能を一般ユーザーが実行できないか/IDを書き換えて認可を回避できないか/画面側だけで制限していないか/利用者から来たID・価格・権限を信用していないか/APIキーや環境変数が応答やログに出ていないか/回数制限が必要なAPIに制限があるか/開発用APIが本番で公開されていないか」を、攻撃の流れと修正案つきで挙げさせると、見落としを探す助けになります。
ただし、確認するAIも間違えます。この点はAIのハルシネーションと同じで、重要なシステムや個人情報を扱うなら、テストや専門家の確認もあわせて検討します。
公開前チェックリスト
扱う情報の重要度と、問題が起きたときの影響が大きい部分から確認します。
- 認証:未ログインで重要APIを呼べないか/パスワードは安全に保存されているか/ログイン試行に制限があるか/再設定URLやコードに有効期限があるか。
- 認可:他人のIDに変えて取得・更新・削除できないか/一般ユーザーが管理者APIを呼べないか/所属外の会社・店舗のデータを見られないか/画面だけでなくサーバ側で権限を確認しているか。
- APIと入力:不要なAPIや開発・デバッグ機能が公開されていないか/利用者から来た価格や権限を信用していないか/入力の形式や長さを確認しているか/DBへの命令を文字列で直接組み立てていないか。
- 機密情報:APIキーがブラウザへ送られていないか/環境変数を画面やAPIで表示していないか/エラーやログに内部情報・認証情報を出していないか/秘密情報をGitHubなどへ登録していないか。
- サーバと運用:HTTPSが有効か/データベースを直接インターネットへ公開していないか/不要なポートを開けていないか/APIの利用回数に制限があるか/ライブラリやサーバを更新できる状態か/バックアップと、異常を確認できるログがあるか。
まとめ
- AIを使えばWebアプリは短時間で作れるが、機密情報をサーバ側に置いただけでは安全にならない。
- 認証は「アクセスしている人が誰か」、認可は「その人がどこまで操作してよいか」。ログイン機能があっても、認可がなければ他人の情報に届かれることがある。
- 画面で隠しても、最終的に許可を決めるのはサーバ。重要な確認はサーバ側で行う。
- 認証・認可のほかに、公開範囲、入力値、秘密情報、ログ、通信、回数制限、更新まで関係する。
- AIに任せる範囲が広がるほど、何を守るかを決める人の判断が効いてくる。落とし穴の全体像はAIで作ったアプリのセキュリティの落とし穴、個人開発での注意は個人開発のセキュリティもあわせてどうぞ。



