見出し画像

【一瞬でサ終(?)】東大男子×女子大生マチアプUTopiaは何がいけなかったのか

2026年4月13日、「男子東大生・女子大学生限定」を謳うマッチングアプリ「UTopia」(https://utopia.tokyo)がリリースされた。駒場キャンパスの掲示板にはビラが貼られ、Twitter上でもそれなりの話題となった。しかし、リリース直後からエンジニアや情報セキュリティに詳しい層から次々と問題点が指摘され、運営は対応に追われることになる。

Twitter上でとりわけ印象に残ったのは、こんな一言のコメントだった。

短い言葉だが、ここには現代のWeb開発、特に バイブコーディング(Vibe Coding) と呼ばれるAI駆動の爆速開発が抱える構造的な問題が凝縮されている。本記事では、UTopiaの何がいけなかったのかを整理しつつ、その背景にある「バイブコーディング × Supabase × セキュリティ」という、いま多くの個人開発者が踏みかけている地雷原について掘り下げていきたい。


UTopiaとは何だったのか

UTopiaは、ランディングページによれば「男子東大生・女子大学生限定」「本人確認で安全」「無料ではじめられる」「プライバシー設計」を売りにするマッチングアプリだ。東大の男女比が男性に偏っているという構造的な「市場の歪み」に着目し、そのマッチング機会を提供することをコンセプトとしていたようだ。

しかしリリース直後から、利用者のリテラシーが高い東大周辺のコミュニティでは、単なる「あり/なし」の好みの議論を超えて、運営体制・法的適正性・個人情報の扱い、そして 技術的な脆弱性 の面から冷静な批判が寄せられることとなった。

リリース直後に指摘された法的・運営面の問題


リリース翌日のツイートにつけられたコミュニティノートは少なくとも以下の3点を指摘している。

(1)インターネット異性紹介事業届出の登録番号が未掲載
マッチングサービスを提供するには、出会い系サイト規制法に基づき公安委員会への届出と登録番号の表示が必要になる。リリース時点でこの登録番号が確認できなかったというのは、「適法に運営されている業者かどうかをユーザー側が検証できない」という意味でクリティカルな問題である。

(2)個人情報認証をマイナンバーカードに限定
本人確認手段としてマイナンバーカードが選ばれていた。これは一見すると「厳格な確認」に見えるが、裏を返せば 「東大生のメールアドレスとマイナンバー情報を、一スタートアップが集約して保持する」 ということを意味する。マイナンバーは税・社会保障・災害対策の目的外使用を原則禁じる「特定個人情報」であり、取扱事業者には厳格な安全管理措置が求められる。個人開発レベルの体制がそれに耐えられるのか、という論点が立ち上がる。

(3)プライバシーポリシーの「外部委託」「事業承継」条項
プライバシーポリシーには、個人情報の取り扱いを外部に委託する可能性、および合併・事業承継に伴い個人情報が第三者に提供される可能性が明記されていた。これ自体は一般的な条項だが、マイナンバーや大学メールアドレスといった高機微情報を扱うサービスが、「プライバシー設計」を前面に出しながらそれを明文化している ことへの違和感が指摘された。

さて、ここまでが「法務・運営面の話」である。しかし本当に深刻だったのは、次の技術的な指摘だった。


 「Supabaseの典型的な問題を踏みまくってる」とは何を意味するのか

UTopiaについて、技術に明るいユーザーから投げられたのが冒頭に引用したコメントだ。ここで何が言われているのかを、順を追って解きほぐしていきたい。

Supabaseとは何か——「バックエンドを書かなくていい」という福音

Supabaseは「Firebaseのオープンソース代替」を謳うBaaS(Backend as a Service)で、PostgreSQLデータベース、認証、ストレージ、リアルタイム同期などを一式で提供してくれる。フロントエンド(Next.js、React等)から直接叩けるクライアントSDKが用意されていて、最大の売りは 「バックエンドを書かずにアプリが作れる」 ということ。

この「バックエンドを書かなくていい」という特性こそが、バイブコーディング勢・個人開発勢・ハッカソン勢に爆発的に支持されている理由であり、同時に 事故が頻発する原因 でもある。

通常のWebアプリは以下のような三層構造をとる。

ブラウザ → APIサーバ(認可チェック) → DB

APIサーバが「このユーザーはこのデータを見ていいか?」を判定してからDBに問い合わせる。ところがSupabaseでの典型的な構成はこうなる。

ブラウザ → Supabase(DB直叩きに近い)

ブラウザから、ほぼ直接データベースを叩ける。ではいったい誰が認可チェックするのか? ここでPostgreSQLの Row Level Security(行レベルセキュリティ、以下RLS) という機能が登場する。「このテーブルのこの行は、このユーザーだけ読める/書ける」というポリシーをDB側に設定しておく仕組みだ。

RLSの設定漏れ

Supabase事故の8割は、これに集約されると言ってもいい。

Supabaseで新しいテーブルを作ったとき、RLSを有効にしてポリシーを書かない限り、そのテーブルは誰からでも読み書きできる。もしくは、逆にRLSを有効化した時点で全アクセスが拒否されるので、「開発中だから」と一時的に無効化して、そのまま本番に出してしまう。これがよくあるパターンだ。

起きる事故は派手だ。

  • ブラウザの開発者ツールからAPIを叩くと、全ユーザーのプロフィール・メッセージ・マッチング履歴が丸ごと取れる

  • ログインしていない匿名ユーザーでも、テーブルの中身を全件取得できる

  • マイナンバーや大学メールアドレスを格納したテーブルが、そのまま閲覧可能になる

マッチングアプリでこれをやると、「誰が誰にいいねしたか」「どのメッセージを送ったか」まで全部漏れる。物理的な安全にまで影響する最悪のパターンだ。

anon keyとservice_role keyの取り違え

Supabaseが発行する鍵には2種類ある。

  • anon key(公開鍵):ブラウザに埋め込んでOK。RLSによって守られる前提。

  • service_role key(管理者鍵)RLSを完全にバイパスする。サーバサイドからのみ使うべき。

このservice_role keyを、うっかりフロントエンドにハードコードしてしまう 事故が後を絶たない。GitHubの公開リポジトリにコミットしてしまったり、Next.jsでNEXT_PUBLIC_プレフィックスを付けてクライアントに露出させてしまったり。

service_role keyが漏れた瞬間、RLSが完璧に設定されていても全く意味がなくなる。DBの全データを誰でも読み書き・削除できる。文字通り一発退場のトラップである。

Storageバケットのポリシー漏れ

Supabase Storage(ファイル置き場)にも同じ構造の問題がある。「本人確認書類」「プロフィール画像」などをアップロードする設計で、バケットをpublicにしてしまう、あるいはアクセスポリシーを書き忘れると、URLを知っていれば誰でもファイルを取得できる状態になる。

さらに厄介なのは、Supabase Storageのファイル名が 推測可能なパターン({user_id}/avatar.jpg、verifications/{user_id}/mynumber.jpg など)で設計されがちなことだ。user_idがUUIDでも、一度パターンが分かれば、ユーザー一覧と組み合わせて総当たりで全員のファイルを取得できる。

マッチングアプリで起きれば、マイナンバーカード画像がこれで漏れる可能性がある。Omiaiの171万件流出事件(2021年)がなぜあれほど重く扱われたか。それは「運転免許証画像」という決定的な本人確認情報が漏れたからだ。UTopiaが保持しようとしていた情報は、それと同等以上に機微なものである。

スキーマ情報は攻撃者に丸見え

Supabase(の裏側で動くPostgREST)は、テーブル定義が分かれば自動的にREST APIを生やしてくれる便利仕様だ。裏を返すと、どんなテーブルが存在し、どんなカラムがあるかが攻撃者から探索可能 になる。/rest/v1/ に適当なテーブル名を投げて200が返ってくれば「存在する」と分かる。

内部管理用のadmin_users、payment_logs、internal_notes、verificationsといったテーブルの存在が推測され、そこにRLS設定漏れが重なった瞬間、全部読めてしまう。

 「関数経由」の抜け穴——Edge Functions / RPC

複雑な処理を書きたいとき、SupabaseではEdge Functions(サーバレス関数)やRPC(PostgreSQLのストアド関数)を使う。ここでも関数内で「呼び出したユーザーが権限を持っているか」をチェックし忘れる パターンが多い。

RLSはあくまでテーブルへの直接アクセスを守るもので、関数経由でデータを取得・更新するとそれを回り込める設計になっている。関数側で明示的に認可チェックを入れないといけないのだが、AIに「この処理をRPCで実装して」と頼んで出てくるコードに、その認可チェックが自動で入るとは限らない。

「いつになったら学ぶんだ」の意味

ここが本題だ。なぜ技術コミュニティの人たちがこうした口調になるかというと、これらの脆弱性は全部、過去に何度も、派手に事故として報道されているから である。

  • 海外のスタートアップがRLS未設定で数十万件の個人情報を流出

  • バイブコーディング製アプリでservice_role keyがGitHub公開リポジトリに平文コミット

  • 2025年、バイブコーディング専用プラットフォーム「Base44」(Wix買収)で認証回避の重大脆弱性をWiz Researchが発見

  • Databricksが「バイブコーディングされたコードは、見た目は動くが致命的な脆弱性を内包しがち」と警告

同じ構造の事故が何年も繰り返されている。Supabase公式のドキュメントには 「RLSを必ず有効にしろ」「service_role keyをクライアントに置くな」 が、繰り返し、太字で、目立つ形で書かれている。

それでも事故が減らない理由は、バイブコーディングそのものの性質 にある。

バイブコーディングという「学ばない」構造

「バイブコーディング(Vibe Coding)」とは、OpenAIのAndrej Karpathy氏が命名した開発手法で、自然言語でAIに指示を出し、生成されたコードをほぼそのまま採用していく開発スタイルを指す。従来のような厳密な仕様書・設計書をすっ飛ばして、「こんな感じのアプリを作って」「ログインもつけて」と指示し、AIが吐き出すコードをコピペしていく。

プログラミング経験が浅い人でも、数日〜数週間でそれらしいWebアプリが動いてしまう。これは革命的な一方で、セキュリティ観点で見ると深刻な構造的問題を孕んでいる。

AIは「動くコード」を書くが「守るコード」は書かない

  • AIに「ログイン機能を作って」と言えば、認証フローは実装される。だが RLSポリシーまで自発的に書くことはまずない

  • AIに「プロフィール編集APIを作って」と言えば、動くAPIは出てくる。だが 「他人のプロフィールは編集できない」というBOLA(Broken Object Level Authorization)対策は入らないことがある

  • AIに「ファイルアップロード機能を作って」と言えば、それは動く。だが MIMEタイプチェックも、サイズ制限も、悪意ある拡張子の拒否も、指示しなければ入らない

AIは優秀な実装者だが、「この機能には認可チェックが必要だ」「この入力は検証が必要だ」と先回りして判断するエンジニアリングの視点を持たない

ドキュメントを読まない文化

バイブコーディングの強みは「ドキュメントを読まずに動かせる」ことだ。ところが、Supabaseのセキュリティドキュメントを読まずにSupabaseをデプロイする のは致命傷になる。このジレンマこそが、「いつになったら学ぶんだ」の背景にある。

スピードへの圧力

マッチングアプリは「ネットワーク効果」で勝負が決まる市場だ。早く、大量にユーザーを集めたほうが勝つ。この構造は、「設計にじっくり時間をかける」という真っ当な判断と相性が悪い。ここで「AIで爆速開発」という誘惑にのれば、当然ながらセキュリティレビューや外部監査のプロセスは削られる。

ブラックボックスの残留

AIが生成したコードは、人間の設計判断の履歴を残さない。数ヶ月後、脆弱性が見つかっても、なぜそう実装したのかを誰も説明できない。メンテナンス困難なブラックボックスが本番で動き続けることになる。


UTopiaは「何がいけなかった」のか

以上を踏まえて整理する。断っておくと、筆者はUTopiaの内部構造を直接検証したわけではないし、運営者を特定して糾弾する意図はない。以下は「一般論としての問題点の整理」である。

スコープと実装能力のミスマッチ

「東大生限定マッチングアプリ」は、個人開発レベルでスタートするには取り扱うデータが重すぎる。マイナンバー認証を実装した瞬間、求められる安全管理措置のレベルは跳ね上がる。マイナンバー法・個人情報保護法・出会い系サイト規制法を横断的に理解し、それを満たすインフラを用意できる体制があったかどうか。技術コミュニティから「Supabaseの典型的な問題を踏みまくってる」と指摘される水準でそれを実装したのだとしたら、扱ってはいけない情報を扱ってしまったということになる。

スピード優先と、検証プロセスの不在

バイブコーディングを使えば数週間でマッチングアプリのMVPが立ち上がる。しかし 「立ち上がる」と「安全に運用できる」は別のレイヤーの話 だ。RLSポリシーの網羅的レビュー、ペネトレーションテスト、脆弱性診断、プライバシーポリシーの法的レビュー——これらは動くコードを書く時間とは別に必要な時間であり、AIが代わりにやってくれるわけではない。

「プライバシー設計」の訴求と実装のギャップ

LPでは「プライバシー設計」と謳いながら、実際のプライバシーポリシーには外部委託・事業承継による第三者提供の条項が入っていた。さらに技術的にも典型的な罠を踏んでいるとすれば、マーケティング上の訴求と実装レベルで乖離が大きすぎる。この乖離に気づいたユーザーの信頼は、一気に崩れる。

法令対応の後回し

インターネット異性紹介事業届出の登録番号がリリース時点で未掲載だった件も含め、「まずは動かして反応を見る」というバイブコーディング文化と、法令対応の文化は原理的に相性が悪い。マッチングアプリ、特にマイナンバーを扱うサービスで「後で直せばいい」は通用しない。


この一件から我々が学ぶべきこと

UTopiaの事例は、個別の企画・実装の巧拙を越えて、これから爆速開発時代を迎える私たち全員に共通する教訓を含んでいる。

AIはコードを書けるが、責任は取ってくれない。 生成されたコードがもたらす脆弱性、漏洩、法的責任は、すべて人間のデプロイ判断に帰着する。

「動く」と「安全に運用できる」は別のレイヤーにある。 バイブコーディングで越えられるのは前者までで、後者は依然として人間の設計判断・レビュー・ペンテスト・監査を必要とする。

BaaSは「バックエンドが消える」わけではない。「バックエンドの責任がDB設定に凝縮される」のだ。 Supabaseを使うということは、RLSポリシーという形でバックエンドの責務を背負うということ。これを理解せずに使うと、むしろ自前でバックエンドを書くよりも危険になりうる。

機微情報を扱うサービスは、爆速開発に向かない。 マイナンバー、健康情報、性的指向、位置情報、未成年者情報——これらを扱う瞬間、開発速度より堅牢性が優先されるべきで、その判断ができるエンジニアリングリードがチームに必要になる。

「学生が作ったから」「個人開発だから」は免罪符にならない。 むしろ、ユーザーも開発者も同じ大学の狭いコミュニティ内にいるからこそ、漏洩時のダメージは物理的距離の近さを伴って返ってくる。


おわりに

UTopia自体が今後どのような形で存続するのか、あるいは実際にサ終するのかは、本稿執筆時点では未確定である。しかし少なくとも、リリース直後に法務・セキュリティの両面から疑問が呈され、運営が火消しに追われる状況は、スタートアップとしては極めて厳しい船出と言える。

バイブコーディングは、個人がこれまで不可能だったスピードでサービスを立ち上げられる、きわめて強力なツールだ。だがその強力さは、「安全に運用する判断ができる人間」がコードとユーザーの間に立っていて初めて 意味を持つ。AIに任せられる範囲を見極め、任せてはいけない範囲を守る——この境界線を引き直すこと。

「Supabaseの典型的な問題を踏みまくってる」というコメントが、次に誰かのプロダクトに投げつけられないために。そして「いつになったら学ぶんだ」と言われる側ではなく、ちゃんと過去の事故から学んでいる側であるために。UTopiaの一件は、私たち全員に対する問いかけとして記憶されるべきだろう。


【4/21追記】
サクラアカウント用意してたのバレてて草。サクラアカウントがあることは大手サービスでもよくある話だが、こんな形でバレてしまえば信頼ゼロだろう。


【4/21 追記2】
別件だが、五月祭常任委員会も情報漏洩をやらかしていた。セキュリティには気をつけよう!


いいなと思ったら応援しよう!

コメント

1
コメントするには、 ログイン または 会員登録 をお願いします。
宮城ゴリ@体外ポルチオの教科書のプロフィールへのリンク

「法的・運営面の問題」についての指摘、かなり重要だよなー。特にインターネット異性紹介事業届出の未掲載は致命的なポイントだと思う。ユーザーとしては、運営がきちんとした体制でやっているかどうかを確認できないのは不安だよね。ここは開発者側ももっと意識してほしいとこだな。

1
【一瞬でサ終(?)】東大男子×女子大生マチアプUTopiaは何がいけなかったのか|東大生AIマニア
word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word

mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1