費用・発注ガイド
セキュリティは後回しにできない:Vibe Codingで最低限やるべき5つの対策
「セキュリティは難しそう」と後回しにしていませんか?本番公開前に最低限やるべきセキュリティ対策を、非エンジニア向けにわかりやすく解説します。
Cursor・Bolt.new・Lovable・v0・Claude Codeでアプリを作っていると、つい後回しにしがちなのがセキュリティだ。
「とりあえず動けばいい」「公開してから考える」...そう思っていないか。
Wiz社のセキュリティリサーチによると、AIが生成したコードの45%に何らかのセキュリティ脆弱性が含まれる。言語別に見るとJavaは10件中7件、JavaScriptやPython・C#でも約40%に脆弱性が確認されている。GitHub Copilotの調査でも、生成コードの40%がOWASP Top 25脆弱性を含むという結果が出ている。
つまり、AIに「セキュアなコードを書いて」と頼んでも、それだけでは足りない。セキュリティの問題は公開後に発覚すると取り返しがつかない。具体的なリスクのパターンはAI生成コードのセキュリティリスク10選で詳しく整理している。
なぜセキュリティを後回しにしてはいけないのか
事例1:APIキーの漏洩
GitHubにコードを公開したら、コードに書いてあったAPIキー(サービスの鍵)が悪用され、100万円の請求が来た。金銭的な損害だけでなく、サービスの信頼失墜・強制停止にまで発展するケースも珍しくない。こうした「クラウド破産」の防ぎ方はAPIキー管理術で解説している。
事例2:個人情報の流出
認証(ログイン)の設定ミスで、他人のユーザー情報が見えてしまう状態になっていた。ニュースで報道され、サービス停止に追い込まれた。ユーザーへの謝罪対応・法的リスクが重なると、個人開発者には致命的なダメージになる。
実例として、位置情報共有アプリ「NauNau」では、クラウドサービスのAPIへのアクセスが不適切に開放されていたことで、少なくとも200万人以上のユーザーの位置情報・チャット履歴が外部から閲覧可能な状態が続いた(2022年9月のサービス開始から2023年4月末まで)。「モバイルアプリの通信を傍受する知識があれば取得できた」とITmediaが報じている。認証なしでアクセスできるAPIが1本残っているだけで、この規模の被害が起きる。
事例3:データの改ざん
入力チェックをしていなかったため、悪意のあるコードを送り込まれ、データベースが全削除された。バックアップがなければ復旧は不可能だ。
これらは実際に起きている事例だ。「小さなサービスだから大丈夫」ということはない。ボットは規模に関係なく常時スキャンしており、脆弱性があれば自動的に攻撃される。
最低限やるべき5つの対策
対策1:APIキーをコードに直接書かない
問題: APIキーやパスワードをコードに直接書くと、GitHubに公開したときに全世界から見える状態になる。
解決策: 環境変数(かんきょうへんすう)を使う
// ダメな例
const apiKey = "sk-1234567890abcdef"
// 良い例
const apiKey = process.env.API_KEY
環境変数は、Vercelなどのホスティングサービスの管理画面で設定できる。ブラウザの開発者ツール(DevTools)のネットワークタブを開いてAPIリクエストを確認し、レスポンスにキーが含まれていないかも必ずチェックする。
チェックリスト:
- コード内に
sk-やapi_keyなどの文字列がないか -
.envファイルが.gitignoreに含まれているか
Supabaseを使っている場合、RLS(行レベルセキュリティ)の設定も重要だ。詳しくはSupabase RLS設定ガイドを参照。
対策2:HTTPSを使う
問題: HTTP(http://で始まるURL)は通信が暗号化されていないため、途中で盗み見られる可能性がある。
解決策: HTTPS(https://で始まるURL)を使う
Vercel、Netlify、Railwayなどのホスティングサービスを使えば、自動的にHTTPSになる。自分で設定する必要はほとんどない。
チェックリスト:
- 本番URLが
https://で始まっているか - ブラウザのアドレスバーに鍵マークが出ているか
対策3:認証をちゃんと実装する
問題: 「ログインしているかどうか」のチェックが甘いと、URLを直接入力するだけで他人のデータが見えてしまう。
解決策: 認証ライブラリを正しく使う
- Supabase Auth:Supabaseを使っているなら最も簡単
- NextAuth.js:Next.jsプロジェクトで広く使われている
- Clerk:設定が簡単で、UIも提供してくれる
認証を実装したら、必ず複数回ログイン・ログアウトのフローを手動テストする。管理者・一般ユーザー・未ログインなどロールごとにテストアカウントを作り、それぞれのアクセス制限が正しく機能しているか確認する。異なるユーザーでログインし直して、他ユーザーのデータが見えないかも確かめる。
チェックリスト:
- ログインしていない状態で、保護されたページにアクセスできないか
- ログアウト後にプライベートなURLへ直接アクセスしても弾かれるか
- 他人のユーザーIDを入力して、他人のデータが見えないか
- 管理者・一般ユーザー・訪問者など、ロール別のアクセス制限が正しく動くか
対策4:入力値をチェックする
問題: ユーザーが入力した値をそのまま使うと、悪意のあるコードを実行される可能性がある。
例えば:
- 名前欄に
<script>alert('ハック')</script>と入力される - 検索欄に
'; DROP TABLE users; --と入力される
解決策: 入力値のバリデーション(検証)を行う
// 例:メールアドレスの形式チェック
if (!email.includes('@')) {
return 'メールアドレスの形式が正しくありません'
}
チェックリスト:
- フォームに変な値を入れても、エラーハンドリングされるか
- HTMLタグを入力しても、そのまま表示されないか
対策5:エラーメッセージに機密情報を含めない
問題: エラーが起きたとき、詳細すぎる情報を表示すると、攻撃のヒントを与えてしまう。
ダメな例:
エラー: データベース接続に失敗しました
Host: db.example.com
User: admin
Password: ●●●●●●
良い例:
エラーが発生しました。しばらくしてから再度お試しください。
詳細なエラーは、ログ(記録)には残しつつ、ユーザーには見せないのが基本だ。
対策6:レートリミットを設定する(見落とされがち)
問題: APIに制限がないと、悪意のあるユーザーがログインを1秒に100回試行できる(ブルートフォース攻撃)。パスワードを総当たりで試されると、いつかは突破される。
解決策: 一定時間内のリクエスト回数に上限を設ける
- Supabase:Auth設定の「Rate Limits」からメール送信・ログイン試行のレート制限を設定できる
- カスタムAPI:
@upstash/ratelimitなどのライブラリで1IPあたりのリクエスト数を制限する
チェックリスト:
- ログインフォームに短時間で大量リクエストを送っても、制限がかかるか
- パスワードリセットメールが連打で大量送信されないか
対策7:本番用と開発用のデータベースを分ける
問題: 開発中のテストデータが本番環境に混在すると、本番でユーザーが偽のデータを見ることになる。「テスト用ユーザー」「ダミー投稿」が実ユーザーの目に触れれば、信頼を損ねる。さらに、開発中に誤って本番データを削除・上書きするリスクもある。
解決策: 環境をコードと設定で明確に分離する
- Supabaseなら本番用プロジェクトを別途作成し、開発用プロジェクトと完全に分ける
.env.local(開発用)と.env.production(本番用)で接続先を切り替える- デプロイ時にVercelの環境変数設定が本番用を指しているか必ず確認する
チェックリスト:
- 開発環境と本番環境で異なるデータベースURLを使っているか
- 本番のデータベースに開発用のテストデータが入っていないか
セキュリティチェックの自動化
自分で全部チェックするのは大変だ。以下のようなツールを使うと、自動でチェックできる。
- GitHub Secret Scanning:APIキーの漏洩を自動検知(無料)
- Snyk:依存パッケージの脆弱性をチェック(無料枠あり)
- Vercel Security Headers:セキュリティヘッダーの設定を確認
- Supabaseセキュリティ診断:アプリのURLを入れるだけでSupabaseのデータ露出リスクを自動チェック(無料)
「セキュリティは専門領域」という現実
ここまで読んで「やっぱり難しい...」と感じた人も多いだろう。
実際、セキュリティは専門知識が必要な領域だ。上記の7つは最低限の対策であり、本番サービスとして運用するには、さらに多くの考慮が必要になる。
- 決済機能がある → PCI DSS準拠が必要
- 医療情報を扱う → 厳格な個人情報保護が必要
- 法人向けサービス → セキュリティ監査への対応が必要
「自分で全部やろう」とせず、セキュリティはプロに任せるという判断も重要だ。後で問題が発覚したときのダメージは、事前に専門家に依頼するコストの何倍にもなる。