メインコンテンツへスキップ
バイブコーディング
セキュリティ
バイブコーディング
AI駆動開発
Next.js
Supabase

個人開発のセキュリティ・チェックリスト — リリース前に最低限これだけ(全部無料)

時間も予算もない個人開発者向けのリリース前セキュリティ・チェックリスト。Supabaseを使うなら最初に確かめる3点(全テーブルのRLS・ブラウザに出してよい鍵・Storageのバケット)と、秘密情報・依存脆弱性・認可・入力検証を全部無料のツールで機械的に潰す手順を解説します。

公開日
最終更新日
最終更新
読了時間
14分
著者
友田 陽大
シェア

最初に結論を述べます。個人開発でセキュリティを守り切る鍵は「水平の統制(アプリ横断で一律に効く対策)を全部無料ツールに機械化させ、自分は縦のリスク(認可・RLS設計)だけに集中する」ことです。 予算も時間もレビュアーもいない1人開発では、注意力に頼った対策は必ず穴が開きます。だから、機械に任せられるところは1コマンドで機械に番をさせ、人間にしか判断できない設計だけに自分の時間を割く——これが唯一スケールする戦い方です。

私は一人 × 生成AI(Claude Code)で経済産業大臣賞を受賞したB2B SaaSを作り、チーム開発の中核エンジニアとして本番二重課金0件の決済基盤を作ってきました。だから断言できます——AIで速く作れるようになったぶん、放っておくと脆弱性も同じ速さで増えます。 でも安心してください。個人開発でリリース前に潰すべき穴は、ほとんどが「決まった場所」に出るので、全部無料のツールで、初回1時間・以後は自動で回せます。 本記事はその実務チェックリストです。


Supabase を使っている場合に最初に確認すること

Supabase では、ブラウザからデータベースへ直接問い合わせが届きます。そのため次の3点が崩れていると、この記事の残りの対策をいくら積んでも、他人のデータが読み書きされます。どれも Supabase の公式ドキュメントが明記している前提です(2026年10月に確認)。

  1. Data API で公開されるテーブルすべてで、RLS が有効か。 公開されているスキーマにあって RLS が無効なテーブルは、権限(grant)を持つロールなら誰でも読み書きできます(Supabase Docs — Row Level Security)。ダッシュボードで作ったテーブルは既定で RLS が有効ですが、SQL Editor やほかのツール(CLI のマイグレーションなど)で作ったテーブルは、自分で有効にする必要があります(Supabase Docs — Securing your API)。
  2. ブラウザに置いているのは、公開してよい鍵だけか。 publishable キー(従来の anon キー)は Web ページやアプリに埋め込む前提の鍵で、RLS が許す範囲にしか届きません。一方、secret キー(従来の service_role キー)は RLS を素通りする鍵で、ブラウザにも、配布するアプリにも、ソース管理にも置いてはいけません(Supabase Docs — API keys)。NEXT_PUBLIC_ で始まる環境変数に secret キーが入っていたら、その時点で公開されています。
  3. Storage のバケットと、そのポリシー。 バケットは既定で非公開で、非公開バケットではダウンロードを含むすべての操作が RLS ポリシーで判定されます。公開バケットにすると、ファイルの URL を知っている人なら誰でも取得できます(Supabase Docs — Storage Buckets)。どの操作を許すかは、storage.objects テーブルに RLS ポリシーを作って決めます(Supabase Docs — Storage Access Control)。本人の書類や写真を入れるバケットが「公開」になっていないかを確かめてください。

確かめ方。 RLS の有効化漏れは、ダッシュボードの Security Advisor が一覧にしてくれます(Supabase Docs — Advisors)。ポリシーの SQL が手元にあるなら /aegis/rls-checker に貼ると、「ログインしているか」しか見ていない書き方や、匿名の訪問者でも書き込める書き方を判定できます(SQL はブラウザの外に出ません)。手順の全体は Next.js × Supabase アプリケーションセキュリティ完全ガイド、鍵の扱いは anonキーとservice_roleキーの正しい扱い、Storage は Supabase StorageをRLSで守る にまとめています。

コードが読めない方へ:Claude Code や Lovable で作ったアプリを公開してよいか不安なら、公開前の診断・レビューか、無料のセルフチェック(登録不要・回答はブラウザの外に出ません)から始められます。


そのAI生成コード、そのままデプロイして大丈夫?

「動いた」の次は「漏れない」— 1コマンドで今のプロジェクトを無料スキャン

1. 個人開発こそ「機械に番をさせる」——水平と縦を分ける

セキュリティ対策は、性質の違う2種類に分かれます。この線引きが個人開発の全戦略です。

水平の統制縦のリスク
何かアプリ横断で一律に効く対策アプリ固有の「誰が何を所有するか」に依存
例秘密情報・依存脆弱性・ヘッダー・入力検証認可 / IDOR・RLS設計・テナント分離・業務ロジック
直せるのはツール(無料で機械化できる)あなた(設計とレビューでしか閉じない)
個人開発の方針1コマンドで自動化し、以後は考えないここに時間を集中投下する

個人開発の失敗は、この2つを混ぜて「全部を気合いで見る」ことから起きます。水平の統制まで手動でやろうとすると疲弊して漏らし、本当に頭を使うべき縦のリスク(認可)に集中力が残らない。機械に任せられるものは機械に、人間にしか無理なものだけ人間に。 発注者視点での全体像はAI生成コードの脆弱性診断【4層で潰す】とAIで作ったコードの本番化(ハードニング)にまとめています。本記事は、その考え方を作り手の1人開発者向けに、無料ツールだけの実務手順へ落とし込んだものです。


2. リリース前チェックリスト(優先順位順・全部無料)

まず全体像です。上から順に、被害の大きさ × 機械化のしやすさで並べています。

#項目何を防ぐ無料ツール初回
1秘密情報を漏らさない鍵・トークンの全世界公開.gitignore / GitHub Secret scanning / npx @aegiskit/cli scan15分
2依存の既知脆弱性既知CVEの放置Dependabot / npm audit10分
3認可(縦のリスク)他人のデータ読み書き(IDOR)/aegis/rls-checker / npx @aegiskit/cli scan20分
4入力を境界で検証注入・不正データZod / npx @aegiskit/cli init10分
5CIで再発を止める一度直した穴の再発GitHub Actions(Aegis / Dependabot)10分

1・2・4は完全に水平(機械の仕事)。3が唯一の縦(あなたの仕事)で、ここだけツールは「検出して警告」までしかできません。以下、1つずつ潰していきます。


3. 秘密情報を漏らさない(最頻・最悪)

被害が最も大きく、しかも一番よく起きるのがこれです。秘密キーがリポジトリに入った瞬間、それは全世界に配布されたと考えるべきです(履歴に残るので、消しても遅い=必ずローテーション)。

やることは3つ。

  1. .env* を絶対にコミットしない。 .gitignore に .env* を入れる。これだけで大半の事故は防げます。
  2. NEXT_PUBLIC_ の罠を理解する。 Next.js では NEXT_PUBLIC_ 接頭辞付きの値がビルド時にクライアントバンドルへ平文で焼き込まれます。ここに service_role キーやAPI秘密を置くと公開されます。仕組み・型付きenv境界・server-only の使い方はNext.jsの環境変数と秘密漏洩対策 — NEXT_PUBLIC_ の罠で実コードごと解説しているので、ここでは繰り返しません。個人開発でも必読の一本です。
  3. 機械に見張らせる。 GitHub の Secret scanning は公開リポジトリなら無料で自動的に動き、混入した認証情報を検知して警告します(GitHub Docs)。加えて npx @aegiskit/cli scan が、ハードコードされた鍵・トークンと「NEXT_PUBLIC_ × 秘密鍵」の組み合わせを形(パターン)だけで拾います。
# インストール不要。いまのプロジェクトを静的解析する
npx @aegiskit/cli scan

正直なスコープを1つ。ツールが機械化できるのは「秘密が混入したこと」の検出です。「その値を公開してよいか」の判断はアプリの意味に依存する人間の設計で、ここは自動化できません。つまり混入は止められても、公開可否は決められない。


4. 依存関係の既知脆弱性を放置しない

自分の書いたコードが完璧でも、依存ライブラリに既知の穴があれば刺されます。ここも完全に機械の仕事です。

  • Dependabot を有効化する(無料)。 リポジトリ設定から Dependabot alerts を有効にすると、GitHub Advisory Database に照らして脆弱な依存を通知し、修正版へのPRを自動で出してくれます(GitHub Docs)。個人開発で「依存を最新に保つ」を人力でやるのは非現実的なので、まず入れる。設定と運用の実務はDependabot 実践導入ガイドとDependabotで脆弱性を管理するにまとめています。
  • ローカルの即席チェックは npm audit。 コミット前に一度回すだけでも、既知CVEの持ち込みを減らせます。
# 既知脆弱性のある依存を即席で確認
npm audit --omit=dev

さらにAI時代固有の罠として、生成AIが実在しないパッケージ名を提案し、攻撃者がその名を先回り登録する「slopsquatting」があります。npm install する前にパッケージの実在とダウンロード実績を確認する癖をつけてください(仕組みと対策はAI生成コードの脆弱性診断で詳述)。


5. 認可を「画面のif文」で済ませない — 唯一の縦のリスク

ここが本丸で、無料ツールが直してくれない唯一の項目です。AIも人間も、認可を「画面のボタンを出す/出さない」で済ませがちですが、APIやDBを直接叩かれれば画面のif文は無意味です。オブジェクト単位の認可欠陥(IDOR / BOLA)は、OWASP API Security Top 10 で長年第1位の最頻出リスクであり続けています(OWASP)。

5-1. 「認証はするが認可しない」を疑う

最頻の事故パターンが、ログインは要求するのに「その行を誰が所有するか」を絞っていないRLSです。Supabase なら、こういうポリシは危険信号です。

-- 危険:ログインさえしていれば「全ユーザーの全行」が読める
create policy "read" on notes
  for select to authenticated
  using ( true );

-- 正しい:自分が所有する行だけに絞る
create policy "read own" on notes
  for select to authenticated
  using ( auth.uid() = user_id );

USING (true) はそのテーブルが本当に公開前提(誰でも読んでよい)なら正しい選択です。問題は、非公開データのテーブルにこれを書いてしまうこと。「認証」と「認可」は別物だという整理はSupabase RLS:authenticated と authorized は違うで詳しく解説しています。

これは机上の心配ではありません。Supabaseを使う公開GitHubリポジトリ1,000件の一次調査で、RLSを持つ994件のうち9.2%が「認証はするが行を所有者に絞らない」ポリシを持っていました(公開リポジトリ標本ゆえ下限値。所有者非スコープ=即脆弱ではなく要確認)。手法と実データはSupabase RLS セキュリティ実地調査にあります。そしてRLS未設定のまま公開して未認証で他人のデータを読み書きされた事例は、実際に CVE(CVE-2025-48757、CVSS 9.3 CRITICAL)として登録されています。

5-2. 無料で「形」の間違いを機械検出する

意味の正しさは人間にしか判定できませんが、「形」の間違いは無料で機械検出できます。 /aegis/rls-checker と npx @aegiskit/cli scan は Supabase の migrations/**.sql を読み、次を警告します。

  • RLSが未設定のテーブル
  • 無条件の USING (true)(公開意図なら可、それ以外は要修正)
  • WITH CHECK 欠落(読めるが書き込み側の所有権チェックが抜けている)
  • search_path を固定しない SECURITY DEFINER 関数(権限昇格の温床)
-- SECURITY DEFINER 関数は search_path を必ず固定する
create function public.get_my_data()
returns setof notes
language sql
security definer
set search_path = ''          -- ← これが無いと path 経由で乗っ取られうる
as $$ select * from public.notes where user_id = auth.uid() $$;

5-3. service_role の置き場所が「守りの境界」になる

Supabase の service_role キーは PostgreSQL の BYPASSRLS で動き、RLSを完全に無視します(Supabase Docs)。つまりこのキーをクライアントやエッジに漏らした瞬間、どれだけ丁寧にRLSを書いても全部無効。守りの境界は「鍵の置き場所」に移るということです。service_role はサーバー専用の秘密として扱い、第3節の秘密情報衛生とセットで守ってください。

ここが唯一「ツールでは閉じない」ところなので、個人開発者が最も頭を使うべきポイントです。/aegis/rls-checker は疑わしい箇所を警告するところまで——閉じるのはあなたの設計判断です。


6. 入力を境界で検証する

外部から来るデータ(フォーム・API・クエリ)は、すべて「敵対的入力かもしれない」前提で境界で検証します。ここは水平(機械化できる)に戻ります。

  • Zod で境界の型検証。 Route Handler や Server Action の入口で、外部入力を必ず Zod でパースしてから使う。「動いたから」で素通しにしない。
  • ランタイム強化を1コマンドで。 npx @aegiskit/cli init は、セキュリティヘッダー / CSP・レート制限・CSRF・型付きenv境界を、ミドルウェア1枚として一括で足します。個人開発で毎回手書きするより、まず入れて土台を固めるのが速い。
# ヘッダー/CSP・レート制限・CSRF・型付きenv境界をミドルウェアで導入
npx @aegiskit/cli init

7. CIで再発を止める(チェックリストを「1回」で終わらせない)

ここまでの対策は、1回やって満足すると必ず腐ります。 AIに機能を足すたびに新しい穴が入るので、チェックを「毎push自動」にして初めて価値が出ます。個人開発でもここは省略しないでください。

  • GitHub Actions に Aegis の CI ステップ(aegis ci)を足すと、高信頼の検出だけがビルドを止め、SARIF が GitHub code scanning に残ります(誤検知でビルドを壊さない設計)。
  • Dependabot・Secret scanning は、有効化した時点で毎pushに効き続けます。

「毎回同じ品質ゲートを機械に通す」考え方そのものはAI駆動開発の品質ゲート(CI・型・テスト・セキュリティ)に、そもそもAIに大規模実装を任せても壊れない進め方はSpec駆動開発 × Claude Codeにまとめています。生成の速さは落とさず、出荷の前に検証を1枚挟む——これが1人でも品質を保つ唯一の型です。


8. 正直なスコープ — 無料ツールで「閉じない」残り

最後に、いちばん大事な但し書きです。「無料ツールを全部入れたから安全」は最悪の油断です。 そう謳う製品はむしろ危険で、npx @aegiskit/cli scan も含め、正直なツールは自分の限界を先に言います。

  • 無料ツールが自動化するのは水平の統制(秘密情報・依存・ヘッダー・入力検証)。
  • 縦のリスク(認可 / IDOR・RLS設計・テナント分離・業務ロジック)は検出して警告するだけ。閉じるのはあなたの設計です。
  • クリーンな結果が意味するのは「よくある罠は踏んでいない」であって「このコードは安全だ」ではありません。

それでも、最頻出の穴を機械的に潰せる価値は個人開発ほど大きい。1人ぶんの注意力を、機械にできる作業から解放して、本当に難しい判断(認可の設計)に集中できるからです。


まとめ:リリース前1時間のチェックリスト

  • .env* を .gitignore に入れ、秘密は絶対コミットしない(漏れたらローテーション)
  • GitHub Secret scanning を有効化(公開リポジトリは無料・自動)
  • Dependabot を有効化 + コミット前に npm audit
  • npx @aegiskit/cli scan を回して水平統制の欠落と縦リスクの疑いを一覧化
  • /aegis/rls-checker で RLS の「形」を確認し、USING(true) の意図を1つずつ検証
  • service_role キーはサーバー専用に閉じ込める
  • (Supabase)Security Advisor で RLS の有効化漏れを確かめ、Storage のバケットが意図せず公開になっていないか見る
  • Zod で境界検証 + npx @aegiskit/cli init でランタイム強化
  • CI(aegis ci / Dependabot)で毎push自動チェックにする

全部無料です。水平は機械に、縦は自分に。 この分担さえ守れば、1人でも「デモは動く」を「本番で漏れない」に引き上げられます。検出された縦のリスク(認可・RLS設計)を実際に塞ぐ設計レビューが必要になったら、そのときはAegisの無料スキャンから始めて、手が足りなければ相談してください。

よくある質問

個人開発で、まず無料で何から手をつければいいですか?
最優先は秘密情報と依存脆弱性です。この2つは完全に機械化でき、被害が最も大きい。.env を .gitignore に入れて絶対コミットしない、GitHub の Secret scanning(公開リポジトリは無料で自動)を有効化、Dependabot(無料)を有効化、そして npx @aegiskit/cli scan を一度回す。ここまでで初回30分、以後は自動です。
無料ツールを全部入れれば、アプリは安全になりますか?
いいえ。そう言うツールはむしろ危険です。無料ツールが自動化できるのは『水平の統制』——秘密情報・依存・ヘッダー・入力検証など、アプリ横断で一律に効く対策です。認可やRLS設計といった『縦のリスク』は、あなたのデータモデルにしか正解がなく、ツールは検出して警告するだけ。閉じるのはあなたの設計判断です。
認可(RLS)は無料でどこまで確認できますか?
『形』の間違いは無料で機械検出できます。/aegis/rls-checker や npx @aegiskit/cli scan が Supabase の migrations を読み、RLS未設定・無条件の USING(true)・WITH CHECK 欠落・search_path を固定しない SECURITY DEFINER を警告します。ただし『この行を誰が所有すべきか』という意味の正しさは人間にしか判定できません。
個人開発だと狙われないから、そこまでやらなくてよいのでは?
逆です。攻撃の多くは人間ではなくボットが無差別に走らせるもので、規模の大小を問いません。Supabaseを使う公開GitHubリポジトリ1,000件の一次調査でも、RLSを持つ994件のうち9.2%が『認証はするが行を所有者に絞らない』ポリシを持っていました(下限値・要確認)。無料で1時間の対策を怠ると、他人のデータが読み書きされる事故(IDOR)に直結します。
Supabaseを使っている場合、最初に何を確認すればいいですか?
3点です。(1) Data APIで公開される全テーブルでRLSが有効か(ダッシュボードで作ったテーブルは既定で有効ですが、SQL Editorやマイグレーションで作ったテーブルは自分で有効にします)。(2) ブラウザに置いているのがpublishable(旧anon)キーだけで、RLSを素通りするsecret(旧service_role)キーが出ていないか。(3) Storageのバケットが意図せず公開になっていないか。RLSの有効化漏れは、ダッシュボードのSecurity Advisorで一覧できます。

参考文献

友田

友田 陽大

経済産業大臣賞 受賞プロダクト開発者。TypeScript + Python + AWS で、SaaS・業界DX・実用レベルの生成AI(RAG)を、要件定義からインフラ・運用まで一人で完遂します。

そのAI生成コード、そのままデプロイして大丈夫?

「動いた」の次は「漏れない」— 1コマンドで今のプロジェクトを無料スキャン

MIT ライセンスの OSS「Aegis」が、AI が見落としがちな統制(ヘッダ/CSP・レート制限・入力検証・秘密情報)を自動化し、認可・RLS 設計の「縦のリスク」は検出・警告します。aegis fix --format json の修正計画は、そのまま Claude Code や Cursor に貼って直させられます。

プロジェクト単位(請負)・技術顧問のどちらにも対応可能です。まずは30分の無料技術相談から。

最短ルート:カレンダーから直接予約

相談内容が固まっている方は、フォーム送信よりその場で日程を確定する方がスムーズです。下記から空き時間をお選びください。

  • 30分のオンライン無料相談
  • Google Meet / Zoom / Microsoft Teams
  • NDA 商談前締結可・無理な営業はいたしません
無料相談の空き枠を予約する

あわせて読みたい