SECTION 01
個人開発のセキュリティは「守る範囲を絞る設計」から始まる
個人開発でセキュリティを考えるとき、最初にやるべきことは防御ラインの選定です。一人で全領域を守り切るのは物理的に不可能なので、「どこを自分で持ち、どこを外部に任せるか」を設計段階で決めてしまいます。
この判断を後回しにすると、公開後に問題が起きたとき対処が追いつきません。事故が起きやすい領域ほど、専門サービスに乗るという原則を持つだけで、個人開発のセキュリティ負荷は大きく下がります。
自分の場合、決済はRevenueCat(iOS/Android両対応の課金インフラ)に任せています。決済まわりのセキュリティや規約対応を自分で全部持とうとすると、コードの品質以前に運用で詰まるからです。ストア申請からクローズドテスト、実機での決済確認というフローで本番に出すことで、自分が抱えるリスクの面積を削っています。
認証も同じ考え方で、Auth.js(OAuth・セッション管理を標準化するライブラリ)やNeonAuthなどに乗っかっています。セッション管理やOAuth周りを自分で組もうとすると、実装の手間よりも見落としのほうが怖いです。自分で持つ領域を以下のように切り分けると判断しやすくなります。
- 自分で持つ: コア機能のビジネスロジック、UI設計、データ構造
- 外部に任せる: 決済処理、認証・セッション管理、インフラ運用
- 判断軸: 事故ったときの被害が大きく、自前実装で穴が開きやすい領域ほど外に出す
40個以上サービスを開発してきた経験からいうと、コア機能以外に時間を使いすぎるとリリースまでの集中力が切れます。セキュリティの話は「どこを自分で持つかの設計の問題」であり、全部を完璧にやろうとする話ではありません。
SECTION 02
公開した瞬間に狙われる。最優先で潰すべき5つの穴
Webアプリを公開すると、即座にスキャンや攻撃の対象になります。利用者が少ない段階では気づきにくいですが、ボットは人間より先にやってきます。まず潰すべき穴を優先順位順に押さえておきましょう。
1つ目はAPIキーのハードコード・リポジトリへの混入です。 これは個人開発者が最も踏みやすい地雷で、開発に集中するあまりシークレット管理を後回しにした結果、公開リポジトリからキーが漏れるケースが後を絶ちません。漏洩したキーは長期間有効なまま放置されがちで、第三者による不正利用が発生するまで気づかないこともあります。
.envファイルで環境変数を管理し、.gitignoreに必ず追加する- コミット履歴にキーが残っていないか確認する
- シークレットスキャンの仕組みを最低限入れておく
2つ目はCORSのワイルドカード設定です。 開発中に動作確認のためワイルドカードで全許可にして、そのまま本番に出してしまうパターンがあります。許可するオリジンは必ず明示的に指定してください。
3つ目は認証・認可の抜け穴です。 ログイン画面だけ守っても、APIエンドポイント単位でアクセス制御ができていなければ意味がありません。エンドポイントごとに「誰がアクセスできるか」を明示的に定義する習慣をつけましょう。
4つ目はSQLインジェクション・XSSなど古典的な脆弱性です。 古典的ですが致命的で、フレームワークが提供するエスケープやパラメータバインディングを素直に使っていれば防げます。自前でクエリ文字列を組み立てないのが鉄則です。
5つ目は依存ライブラリの既知脆弱性です。 npm auditやDependabot(GitHubが提供する依存関係の脆弱性自動検出)を有効にしておくだけで、既知の問題は自動で検出できます。
- 最低限やること:
npm auditを定期的に実行する - 自動化: Dependabotを有効にしてPRを受け取る
- 判断: criticalとhighだけ即対応し、lowは次のメンテ時にまとめる
SECTION 03
AI生成コード時代に増えた、個人開発特有のリスク
AIを使ったコード生成が当たり前になった今、セキュリティの落とし穴はむしろ増えています。手軽に開発できるようになった分、検証を省いたままコードが本番に投入されるケースが急増しているのが現実です。
AIが生成するコードには、認証の抜け穴や設定ミスが含まれやすいという構造的な問題があります。AIはコードを「動くように」書きますが、「安全に動くように」書くとは限りません。たとえば認可チェックが抜けたAPIエンドポイントや、デフォルトで甘い設定のまま出力されるコードは珍しくありません。
個人開発では、このコードをレビューなしで本番投入する習慣がセキュリティ負債を積む構造になっています。チームであれば誰かが「この設定おかしくない?」と気づけますが、一人ではその機能が働きません。組織的なチェック機能がない環境で、検証されていないコードが積み重なっていく怖さを認識しておく必要があります。
では、どうやって最低コストでセキュリティチェックを回すか。以下のような仕組みを入れておくだけで、大きな見落としは防げます。
- AIにセキュリティレビューを頼む: コード生成後に「このコードのセキュリティ上の問題を指摘して」とそのまま聞く
- リンターとセキュリティスキャン: ESLintのセキュリティプラグインなどを導入しておく
- 公開前の最終確認: 認証・認可・入力検証の3点だけは手動で確認する
AIが書いたコードを信頼しすぎないこと。「動いた」と「安全に動いている」は別物だという前提で、最低限の検証レイヤーを挟む習慣が個人開発者の防御ラインになります。
SECTION 04
インフラで守る。プラットフォームに乗せるだけで減るリスク
MENTAというメンターマッチングサービスでは、サーバー管理も自分でやっていた時期があります。ユーザーが実際に使っているサービスのインフラを一人で持つことの重さは、時間的にも精神的にも身体でわかっています。だから今は、インフラ部分は実績のあるプラットフォームに乗せる構成を選んでいます。
自前サーバーを持つということは、OSのアップデート、セキュリティパッチの適用、ログの監視、障害対応のすべてが自分の責任になるということです。個人開発者がこれを継続的に回すのは現実的ではありません。 VercelやCloudflareのようなプラットフォームに乗せるだけで、これらの負荷を構造ごと下ろせます。
「守りたいけどお金がない」という個人開発者の現実に対して、プラットフォーム選びで解決できる部分は想像以上に大きいです。
インフラのセキュリティは、自分の努力で守るものではなく、どこに乗るかを選ぶことで構造的に守るものです。一人で持つべきでない責任を、設計段階で手放す判断がポイントになります。
SECTION 05
データを持たない設計が最強の防御になる
セキュリティの観点で最も効果的な戦略は、そもそもデータを持たないことです。持つデータが増えるほど守る面積が広がり、漏洩時の被害も大きくなります。これは技術的な問題というより、設計思想の問題です。
自分はサービスの初期段階でログイン不要で始められる体験を好んでいます。UXの観点で摩擦を減らしたいというのが主な理由ですが、ユーザーデータを持つ量が増えるほど守る対象も増えるという構造的な問題にも直結しています。まずデータを持たないシンプルな構造から始めることで、運用負荷を下げられます。
データを持つかどうかの判断は、以下の順序で考えると整理しやすいです。
- 持たなくて済むなら持たない: ログイン不要で使える範囲を最大化する
- 持つなら最小限にする: 本当に必要なデータだけを保存する
- 持つなら守り方を先に決める: バックアップ、暗号化、アクセス制御を保存前に設計する
「最初はシンプルに、必要になってから段階的にデータを持つ」という方針は、機能追加の判断軸としても有効です。ユーザー登録機能を入れた瞬間にメールアドレスの管理責任が発生し、決済機能を入れれば取引情報の保護が必要になります。機能を追加するたびにセキュリティの責任範囲が広がることを意識しておきましょう。
最初から複雑な状態管理を抱えないほうが、後で詰まる箇所が減ります。これはセキュリティだけでなく、個人開発の持続性そのものに関わる設計判断です。守る対象が少ないほど、一人でも守りきれます。
SECTION 06
見落としがちなHTTPヘッダーとCORS設定の実務
セキュリティ対策というとコードの脆弱性に目が行きがちですが、HTTPヘッダーの設定不備も個人開発者が見落としやすいポイントです。ブラウザが提供するセキュリティ機能を、ヘッダー一つで有効にできるのに使っていないのはもったいないです。
最低限設定しておくべきヘッダーは以下の通りです。
- Strict-Transport-Security: HTTPSを強制し、中間者攻撃を防ぐ
- X-Content-Type-Options: nosniff: MIMEタイプの誤認を防ぐ
- X-Frame-Options: クリックジャッキング攻撃を防ぐ
- Content-Security-Policy: 許可するリソースの読み込み元を制限する
VercelやCloudflareを使っていれば、設定ファイルやダッシュボードから簡単に追加できます。フレームワーク側で対応している場合も多いので、自分の構成で何が自動適用されていて何が手動設定なのかを一度確認しておくとよいです。
CORSについては、開発中に全許可にしたまま本番に出すケースが本当に多いです。許可するオリジンは必ず明示的に列挙してください。 Access-Control-Allow-Origin: *は開発環境でしか使わないルールを徹底するだけで、一つの攻撃経路を潰せます。
ヘッダー設定は一度やれば終わるものがほとんどです。最初に正しく設定しておけば、以降の運用コストはゼロに近いので、公開前のチェックリストに入れておくべき項目です。
SECTION 07
依存ライブラリとサプライチェーンリスクへの向き合い方
個人開発ではnpmパッケージやライブラリを多用しますが、それぞれが潜在的な攻撃経路になり得るという認識を持っておく必要があります。サプライチェーンリスクは大企業だけの問題ではなく、個人開発者の規模でも起こり得ます。
ライブラリを「信頼できるもの」として無条件に使い続ける習慣が、気づかぬうちにリスクを蓄積させます。特に小規模な開発では依存関係の管理が手薄になりやすく、定期的なスキャンが行われないことが多いです。
対策としては、以下を最低限の運用ルールにしておきます。
npm auditを月1回は実行する: criticalとhighを優先的に対応- Dependabotを有効にする: GitHubリポジトリなら設定一つで自動PRが来る
- 不要なパッケージを定期的に削除する: 使っていない依存は攻撃面積を無駄に広げる
すべての脆弱性を即座に修正する必要はありません。重要度の高いものだけを優先し、低リスクなものはメンテナンスのタイミングでまとめて対応するのが現実的です。完璧を目指すのではなく、致命的な穴を塞ぐことに集中しましょう。
依存ライブラリのセキュリティは、一度設定すれば自動で回り続ける仕組みにできます。最初の設定に少し時間をかけるだけで、その後の運用負荷はほとんどかかりません。
SECTION 08
シークレット管理の基本。漏れたら終わりの情報を守る
APIキー、データベースの接続文字列、外部サービスのトークン。これらのシークレット情報が漏れたときの被害は即座に広がります。個人開発者にとって、シークレット管理はセキュリティの最も基本的な防御ラインです。
やるべきことはシンプルですが、開発に集中しているとつい後回しにしがちです。
- 環境変数を使う: コードにハードコードしない。
.envファイルで管理する .gitignoreに.envを追加する: リポジトリに混入させない- 本番とローカルで別のキーを使う: 開発用キーが漏れても本番に影響しない構成にする
すでにコミット履歴にキーが入ってしまった場合、.gitignoreに追加しただけでは履歴から消えません。この場合はキーを即座に無効化して新しいキーを発行するのが最も安全な対応です。履歴のクリーンアップよりも、漏れた前提で動くほうが確実です。
VercelやCloudflareなどのプラットフォームには、環境変数を安全に管理するダッシュボードが用意されています。本番環境のシークレットはこれらの仕組みを使い、ローカルの.envファイルとは分離して管理しましょう。
シークレット管理を正しくやるだけで、個人開発で起きるセキュリティ事故の大部分を防げます。地味だけれど、最もコストパフォーマンスの高い対策がここです。
SECTION 09
事故が起きたときの初動。一人でもパニックにならないために
セキュリティ事故は「起きるかどうか」ではなく「起きたときにどう動くか」の問題です。初動の速さが被害の大きさを決めます。 個人開発者だからこそ、事前に動き方を決めておくことが重要です。
APIキーが漏洩した場合の初動は以下の通りです。
- 即座にキーを無効化する: 影響範囲を確定する前に、まず止める
- 新しいキーを発行して環境変数を更新する: サービスの復旧を優先
- アクセスログを確認する: 不正利用の痕跡があるか調べる
ユーザーデータに影響が及んだ場合は、影響範囲の特定とユーザーへの通知が必要になります。何が漏れた可能性があるのか、いつからいつまでの期間か、ユーザーが取るべきアクションは何か。これらを整理して、正直に伝えることが信頼を守る最善の方法です。
事故対応で最もまずいのは、「たぶん大丈夫だろう」で何もしないことです。小規模だから狙われないだろうという判断は危険で、ボットによる自動攻撃は規模を問わず行われます。少しでも怪しい兆候があれば、過剰反応くらいでちょうどいいです。
事前にやっておくと安心なのは、各サービスのキー無効化手順をメモしておくことです。事故が起きてから管理画面を探し始めると、焦りで判断が鈍ります。冷静なときに手順を確認して、すぐアクセスできる場所に置いておきましょう。
SECTION 10
一人でも回せるセキュリティ運用チェックリスト
ここまでの内容を、公開前と公開後に分けたチェックリストとして整理します。一人で全部を完璧にやる必要はありませんが、このリストの上位項目だけは確実に押さえておきましょう。
公開前に確認すべきことはこちらです。
- 環境変数でシークレットを管理し、
.gitignoreに.envを追加した - CORSの許可オリジンを明示的に設定した
- 全ページがHTTPSで配信されている
- セキュリティ関連のHTTPヘッダーを設定した
- APIエンドポイントごとに認証・認可を確認した
npm auditで重大な脆弱性がないことを確認した
公開後に定期的にやることは以下の通りです。
- 依存ライブラリの更新(月1回以上)
- アクセスログの異常確認(週1回程度)
- APIキーのローテーション(利用サービスの推奨頻度に従う)
- Dependabotからの通知対応(criticalは即日)
このチェックリストの要点は、「一回やれば終わるもの」と「継続的にやるもの」を分けることです。公開前の項目はほとんどが一度の設定で済みます。公開後の項目も、自動化できるものはDependabotやCI/CDに任せれば、手動でやることは最小限に抑えられます。
個人開発のセキュリティは、完璧を目指す話ではなく、致命的な穴を塞ぐ話です。守る範囲を絞り、専門サービスに任せるところは任せ、自分が見るべきポイントだけに集中する。この設計思想があれば、一人でも十分な防御ラインを維持できます。
