公開サービスをpublicリポジトリで開発するということ
- GitHub
- OSS
- セキュリティ
Bitwarden というパスワード管理サービスは、サーバーからクライアント、ブラウザ拡張まで、すべてのソースコードを GitHub で公開している1。利用者のパスワードを預かる立場でありながら、コードを隠すどころか、公開していることを製品の売りにしている。同じようにコードを公開しながら事業として成り立っているサービスは、GitLab や Sentry、Plausible、Cal.com、Signal など、身近なところに多い。
それでも自分で公開サービスを作る段になると、public リポジトリにする判断にはためらいが出る。不安は2つに整理できる。ソースを公開すれば攻撃の手がかりを与えるのではないかという不安と、そのままコピーされて商売にならないのではないかという不安だ。この記事では、この2つを順に検証したあとで、公開して得られるもの、公開することで生じるデメリット、そして何をコードと別に置くべきかを書く。
コードが見えることと、システムが破られることは別
暗号の分野では、仕組みがすべて知られていても、鍵が漏れない限り安全であるべきだという原則が 19 世紀から知られている。Kerckhoffs の原則2と呼ばれ、AES や TLS といった現代の暗号は、仕様と実装を公開した上で設計されている。銀行の通信が破られないのは、安全を支えているのが仕組みの秘密ではなく鍵の秘密だからだ。
サービスのコードも同じで、守らなければならないのはコードではなく、API キーと認証トークン、データベースの接続情報、署名鍵、本番環境へのアクセス権である。これらは private リポジトリで開発していてもコードとは別に管理するのが本来の姿だ。言い換えると、コードを隠しているから安全だと感じている状態は、脆弱性がすでにあってまだ見つかっていないだけの状態と区別がつかない。ここ数年の情報漏えいを振り返っても、原因の多くはコードが読まれたことではなく、認証情報の流出や設定の誤りに集中している。
public リポジトリで開発すると、この分離を最初から強いられる。秘密は環境変数かシークレットマネージャーに出し、コミットには混ぜない。手間に見えるが、あとから直すと最も高くつく設計を最初から正しい形にしておくことになる。GitHub の secret scanning は public リポジトリでは無償で動いており、コミットに混入した AWS や Stripe の鍵は数分で検知され、発行元に通知されて無効化される3。攻撃されるのではないかという不安は、設計と運用の問題であって公開そのものの問題ではない。
コピーされても、持っていかれないものがある
コードをコピーしても、利用者とそのデータ、ドメインと検索での認知、運用を続けてきた履歴、不具合に対応してきた実績は一緒には持っていけない。サービスの価値の大半はこちら側にある。GitLab はコードがすべて公開されている4が、フォークして競合サービスとして成功させた例はない。Plausible は AGPL でコードを公開5しつつ有料のホスティングで事業を続けている。利用者が払っているのはコードの対価ではなく、自分で運用する手間を引き受けてもらうことへの対価だ。個人開発に限って言えば、模倣されるリスクよりも、模倣される前に誰にも知られず終わるリスクのほうがはるかに大きい。
さらに 2026 年の今は、コードを隠していても画面と挙動を見せれば AI エージェントが数時間で利用者にとっては同じものを作ってしまう。クローズドにしておくことが模倣を防ぐ効果は、この数年でほとんどなくなった。アイデアと外見がすぐにクローンされるということは、裏を返せば、利用者から見て差がつく場所は外見にはもう残っていないということでもある。残っているのは内部で、内部のコードまで公開して仕組みがしっかりしていると示すことだけは、クローンの側には真似ができない。真似をするには向こうも公開するしかなく、そうなればそれはもうクローンとは呼べない。
公開して得られるもの
隠すことで守れるものがもともと小さく、今はさらに小さくなっているのだとすれば、公開して得られるものが少しでもあれば公開したほうが得になる。得られるものはいくつか重なっている。
信用は内部でしか示せない
外見は誰でも同じものが作れるので、利用者が差を見つけられるのは内部しかない。プライバシーポリシーに第三者提供はしないと書くのは誰にでもできるが、データをどこに送っているかをコードで確認できる状態は、その文章とは別のものだ。会社の看板を持たない個人開発者にとって、これは信用を得るほとんど唯一の手段になる。Bitwarden がコードの公開を売りにしているのも、パスワードを預ける相手を選ぶ利用者にとって、この確認可能性が一番欲しいものだからだろう。
確認するのは人間ではなく AI
利用者は「このサービスは自分のデータをどう扱っているのか」を AI に聞き、AI は public リポジトリをそのまま読んでコードを根拠に答える。コードを読めない利用者にも、公開しているかどうかの差が答えの質の差として届く。自分が AI と開発するときも同じで、リンクを1つ渡せば文脈が伝わる。公開されたコードは、人間が読まなくても機械が読んでいる。
実績と継続性
作者自身の実績にもなる。履歴書にサービスを開発・運用したと書くより、動いているサービスとそのコード、コミット履歴のほうが評価する側にとって情報量が多い。サービスの継続性も担保される。作者が手を引いてもフォークで生き残る道があり、利用者はそれを知っているから個人の作ったサービスにもデータを預けられる。
バグ報告や翻訳の PR、セキュリティ研究者からの連絡を受け取る窓口にもなる。ただし個人のリポジトリに届く量は少なく、ここに期待しすぎると危ない。この点は次で触れる。
コストが下がる
即物的な話として、GitHub の機能の多くが public リポジトリでは無償になる。
| 機能 | public | private |
|---|---|---|
| GitHub Actions | 利用時間の上限なしで無償 | 月 2,000 分まで。超過分は課金6 |
| CodeQL | 無償 | GitHub Advanced Security(有償)7 |
| secret scanning / push protection | 無償 | GitHub Advanced Security(有償) |
| Dependabot | 無償 | 無償 |
| private vulnerability reporting | 無償 | 対象外 |
| GitHub Pages | 無償 | 有料プランが必要 |
Sentry や Vercel、1Password、JetBrains のように、OSS 向けの無償プランを用意している SaaS も少なくない。
このコスト差は、以前なら気にしなくてもよいものだった。しかし AI エージェントに開発を任せるようになると、コミットと CI の実行回数は、人間が書いていたころの数十倍に増える。エージェントは自分の変更が正しいかをテストを回して確かめるので、CI は開発の付属品ではなく開発の中身そのものになった。GitHub にとって public リポジトリの増加はそれ自体が価値なので、public リポジトリの CI を無償にしている。開発者はその利害に乗ることができる。どの SaaS が OSS に何を無償で提供しているかは、別の記事でまとめる。
デメリット: 「多くの目」は個人のリポジトリには届かない
OSS は安全だという通説がある。それが成り立つのは、使う人が多いから脆弱性が見つかって報告され、直されるという循環が回っているときに限られる。Linux カーネルや OpenSSL にはその循環が働くが、個人の public リポジトリには働かない。誰も読まないからだ。
明らかに SQL インジェクションが通るコードを public に置いていても、善意の報告が来ることはまずない。使う人の多い OpenSSL でさえ、Heartbleed は公開されたコードの中に 2 年間気づかれないまま残っていた8。読む人がいないリポジトリは、読めるというだけで読まれてはいない。
一方で、攻撃する側は読む。正確に言えば人間ではなくスキャナが読む。GitHub 上の public リポジトリを網羅的に巡回して既知の脆弱なパターンを探すことは、今では誰にでもできる。前半で書いた「隠しても守れない」は正しいが、「見せても同じ」ではなく、差は見つかるまでの時間に出る。善意の目は届かないのに、悪意のスキャナは届く。この非対称が、個人が public で開発するうえでの最大のデメリットだ。
埋めるのはやはり機械で、人の目の代わりに public リポジトリに対して無償で動く自動検査を積み上げる。GitHub の CodeQL、Dependabot、secret scanning に加えて、Snyk、Semgrep、Socket、Trivy、Aikido など、OSS には無償で開かれている SaaS がいくつもある。private リポジトリでは有償か制限付きになるものが多いので、公開することで生じるリスクを、公開しているからこそ使える道具で相殺する形になる。個人の public リポジトリの安全は、コミュニティではなくこの積み上げで成り立たせるものであって、誰かが見てくれるという期待は最初から持たないほうがよい。
公開したことそのもので起きる事故は四種類
- 秘密情報の混入。.env や認証トークンをコミットしない。一度履歴に入った鍵は消しても残るので、漏れたら削除ではなく無効化で対処する。secret scanning の push protection を有効にしておけば、混入した push はその場で拒否される。
- ライセンス。コードをそのまま SaaS として転売されたくないなら AGPL、広く使ってもらいたいなら MIT や Apache 2.0。ライセンスを書かないままだと、公開していても法的には誰も使えない。サービス名とロゴはコードとは別で、商標の考え方で守る。
- 脆弱性が見つかったときの扱い。報告を public の Issue で受けてはいけない。GitHub の private vulnerability reporting9 を有効にし、SECURITY.md で窓口を示す。修正を push した瞬間に差分が公開され、差分は脆弱性の場所をそのまま指すので、本番へのデプロイを済ませてから push する。
- 対応の負荷。Issue や PR が来ても全部に応じる必要はない。README に個人のプロジェクトであり対応は保証しないと書いてあれば十分だ。
Terraform や Kubernetes のマニフェストを公開するとインフラ構成が全部見えるが、それ自体は脆弱性ではない。気になるならそこだけ別リポジトリに分ければよい。ここに挙げたものはいずれも、コードを公開するかどうかの話ではなく、何をコードと別に置くかの話だ。
公開しない部分の切り分け
公開しないほうがよいものは、知られると回避される性質のものに限られる。不正利用の検知ロジック、スパム判定の閾値、レート制限の具体的な数値、料金計算の例外、取引先との契約に関わる部分などだ。これらは設定値として環境変数に出すか、小さな private リポジトリや private なパッケージに分けておく。Sentry や GitLab が商用機能を別ディレクトリや別ライセンスに切り分けているのと同じ考え方だ。分けた結果として、コードの 9 割は public、残りが設定と秘密という構成に落ち着く。この構成は public にしなくても本来そうあるべきもので、public にするということは、その設計を後回しにできなくするということにほかならない。
見せても安全だから、見せているから預けてもらえる
冒頭の疑問に戻る。パスワードを預けるサービスがコードを全部見せているのは、見せても安全な設計だからである。同時に、見せているからこそ預けてもらえる。この2つは同じことの表と裏にあたる。AI がコードを書く時代に、コードそのものの希少性は下がっていく。残るのは「誰が、何のために、どう運用しているか」という信用である。それを示すいちばん安い方法が public リポジトリで開発することだ。