◉RORK LABEN
●EXPO — EAS Observe がネイティブクラッシュも記録(10/07)。SDK 57 は 57.0.21 以降で確認できます●SDK 58 — SDK 58 Beta は 9/15 公開。stable の日付はまだ未確認です●RN 0.88 — React Native 0.88.x の正式リリース予定は 10/12、残り3日●Q&A — expo-widgets が本番ビルドだけ真っ黒になる、という問いが出ています●RORK — 09-29 に GPT-6.1 Sol を追加。Pro・Max プランで利用できます●NEW — クライアントのアプリを作る前に決める、公開アカウントの持ち主●EXPO — EAS Observe がネイティブクラッシュも記録(10/07)。SDK 57 は 57.0.21 以降で確認できます●SDK 58 — SDK 58 Beta は 9/15 公開。stable の日付はまだ未確認です●RN 0.88 — React Native 0.88.x の正式リリース予定は 10/12、残り3日●Q&A — expo-widgets が本番ビルドだけ真っ黒になる、という問いが出ています●RORK — 09-29 に GPT-6.1 Sol を追加。Pro・Max プランで利用できます●NEW — クライアントのアプリを作る前に決める、公開アカウントの持ち主
記事一覧/開発ツール
⬡ 開発ツール/2026-07-10上級

クライアントに置いた鍵は公開情報 — Rork 生成アプリの秘密境界とローテーション手順

生成された Expo アプリの .ipa を展開すると、環境変数がそのまま文字列として現れます。鍵を3層に分類し、置けないものをプロキシへ逃がし、漏れた前提のローテーション手順書を用意するまでの設計をまとめます。

Rork577セキュリティ13Expo213環境変数7運用設計8

✦ プレミアム記事

ビルド済みの .ipa を手元で展開し、strings を通したのは、ある夜のことでした。

出力の中に、自分が EXPO_PUBLIC_ANALYTICS_KEY と名付けた文字列がそのまま並んでいました。難読化もエンコードもされていません。ビルドから抽出まで、かかった時間は10秒ほどです。

頭では知っていたはずのことでした。それでも、自分のアプリのバイナリから自分の鍵が読み上げられるのを目で見た瞬間、背筋が冷えました。

個人開発で6本のアプリを並行して運用していると、鍵の本数はすぐに二桁になります。広告、課金、分析、クラッシュレポート、翻訳 API。生成 AI にアプリの骨格を書いてもらうと、それらの初期化コードは驚くほど素早く揃います。ただし「その鍵をどこに置くべきか」という判断だけは、生成物の外側に残されたままです。

この記事は、その判断を自分の中で言語化し、6本のアプリに一巡させた記録です。

クライアントに置いた鍵は、暗号ではなく公開情報

まず前提を固めます。モバイルアプリのバンドルは、ユーザーの端末に配布される時点で「読める状態」になります。

Expo(React Native)であれば JavaScript バンドルの中に、Swift であればバイナリの文字列テーブルの中に、鍵は文字列として存在します。難読化はコストを上げますが、境界にはなりません。

実際に確認してみるのが最短です。手元のビルド成果物に対して次を実行します。

# iOS: .ipa は zip なので展開してバイナリに strings を通す
unzip -q MyApp.ipa -d /tmp/ipa
strings /tmp/ipa/Payload/MyApp.app/MyApp | grep -iE 'key|secret|token' | head -20
 
# Expo(JS バンドル): バンドル本体を直接 grep する
grep -oE 'EXPO_PUBLIC_[A-Z_]+"[^"]*"' /tmp/ipa/Payload/MyApp.app/main.jsbundle | head -20
 
# Android: apk からも同様に取り出せる
unzip -q app-release.apk -d /tmp/apk
strings /tmp/apk/classes.dex | grep -iE 'AIza|sk_live|pk_live' | head

この3コマンドで、自分のアプリが何を公開しているかが分かります。私はこれを、新しいアプリをストアに出す前の儀式にしました。

ここで見つかった文字列は、すべて「公開情報」です。隠すのではなく、公開されても損害が出ない設計にするしかありません。

鍵を3つの層に分類する

「秘密かどうか」の二択で考えると判断が止まります。実運用では3層に分けると、置き場所が自動的に決まります。

層 性質 具体例 置き場所 漏洩時の影響
層1: 公開識別子 そもそも秘密ではない AdMob アプリ ID / ユニット ID、RevenueCat の公開 SDK キー、Sentry DSN クライアントに直書きで可 実質なし(悪用は別の防御層で止める)
層2: 制限付き公開鍵 公開前提だが制約が必須 Firebase Web API キー、Maps API キー、分析の書き込み専用キー クライアント可。ただし発行元でバンドル ID・リファラ・スコープを制限する 制限が甘い場合のみ従量課金の被害
層3: 真の秘密 持つ者がサーバーとして振る舞える OpenAI / Gemini の API キー、Stripe シークレットキー、RevenueCat のシークレット API キー、Supabase の service_role キー クライアント禁止。サーバー / エッジ関数のみ 課金の直撃、データ全件の読み書き

判定に迷ったときの問いはひとつです。「その鍵を持った他人が、私の代わりに課金できるか、私のデータを全件読めるか」。答えが「はい」なら層3であり、EXPO_PUBLIC_ を頭に付けた瞬間に負けが確定します。

層2で最も見落とされやすいのは、発行元での制限です。Google Cloud のコンソールでキーに「アプリケーションの制限(Android パッケージ名 / iOS バンドル ID)」と「API の制限(このキーで叩ける API の列挙)」を設定していない鍵は、層2のふりをした層3です。

環境変数そのものの読み込みでつまずいている段階であれば、先にRork で環境変数が読み込まれないときの原因と対処を確認しておくと、この先の話が地続きになります。

✦

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
✦アプリバンドルから環境変数を実際に抽出して確認する手順と、その結果に基づく鍵の3層分類
✦クライアントに置けない鍵をエッジプロキシへ逃がす、そのまま動く実装とレート制限の考え方
✦「漏れている前提」で回すキーローテーション手順書と、CI で再発を止める検査スクリプト
Stripe による安全な決済 · いつでもキャンセル可能
✦

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥2,480 の永久アクセス
メンバーシップを見る →

関連記事

⬡ 開発ツール2026-09-04
EAS の secret は「アプリに入れない」設定ではありません — 接頭辞と可視性を別々に決める
EXPO_PUBLIC_ の接頭辞は成果物に入るかを決め、EAS の可視性は誰が読めるかを決めます。二つを重ねたときに OTA 更新でだけ値が消える筋道と、出荷前に自分の手で確かめる手順をまとめました。
⬡ 開発ツール2026-10-07
日本語の見出しだけ太字にならない — Android で fontWeight が効かないときの切り分けと直し方
Rork で作ったアプリで、iPhone では太字なのに Android では日本語の見出しが細いままになる症状の切り分け記事です。原因の見分け方、fontFamily を重みごとに分ける直し方、確認用コードを載せています。
⬡ 開発ツール2026-09-21
exit code 0 で止まるビルド — ログを黙らせていた設定と、空ファイルを通した存在チェック
eas build --local が exit code 0 but produced no further output で止まる件と、0 バイトのスタブが埋め込まれず dyld で落ちる件。どちらも原因は出力を減らす設定でした。自分のスクリプトを棚卸しする手順まで書き残します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます