Upgrade to Pro — share decks privately, control downloads, hide ads and more …

機密情報の漏洩を防げ! Webフロントエンド開発で意識すべき漏洩パターンとその対策

Avatar for mizdra mizdra PRO
November 15, 2025

機密情報の漏洩を防げ! Webフロントエンド開発で意識すべき漏洩パターンとその対策

YAPC::Fukuoka 2025 で発表した資料です。

Avatar for mizdra

mizdra PRO

November 15, 2025
Tweet

More Decks by mizdra

Other Decks in Technology

Transcript

  1. 4 機密情報 • 機密情報と言っても色々ある ◦ 個人情報 (メールアドレス, 住所) ◦ 業務上の情報

    (開発環境のドメイン, 未公開のキャンペーン情報) ◦ 認証情報 (API トークン, Cookie) ◦ ログ (アクセスログ、アプリケーションログ) ◦ ソースコード • 要は漏れるとマズいもの
  2. 5 Web フロントエンドにおいては • 漏れないように注意して開発しようという話ではある • ただし Web フロントエンドフロントエンドでは... ◦

    機密情報の漏洩が起きやすい • 何故か ◦ ユーザに面してる ◦ HTML や JavaScript がブラウザから読める • 見える情報が多いゆえに脆弱
  3. 6 最近の Web フロントエンドは 落とし穴が結構ある • モダンなフロントエンドフレームワークでは... ◦ 機密情報を漏洩させやすいポイントがある •

    フレームワークの裏側の挙動を知ってれば回避可能だが... ◦ 知らないとハマる ◦ テンプレートエンジン (Xslate, erb) に慣れてる人ほどハマりやすい
  4. 7 このセッションの目的 モダンな Web フロントエンド開発で漏洩を防ぐための知識 と術を伝えます。 • 従来技術 (Xslate, erb)

    との違い ◦ なぜモダンなフロントエンド FW は漏洩させやすいのか ◦ 漏洩を防ぐにはどうしたら良いのか • 漏洩の有無を調べる方法 • うっかり漏洩するのを防ぐテクニック
  5. 8 おことわり • React, Next.js の話が割と多め • とはいえ他の View ライブラリ/FW

    に適用可能な話もある • 最もメジャーな流派の事情を知るのは良いこと
  6. 10 従来技術とは • ここでいう従来技術というのは... ◦ Xslate (Perl), erb (Ruby), PHP

    ◦ いわゆるテンプレートエンジン • リクエストが来たら、サーバでテンプレートをレンダー ◦ HTML を返す
  7. 12 最近の Web フロントエンド開発 • JS の View ライブラリを使って UI

    を組むのが主流 ◦ React, Vue.js, Angular, … • ブラウザ上でコンポーネントをレンダーするだけでなく ◦ SSR (サーバー上でレンダー) するのが当たり前 ◦ SSR をサポートする FW (Next.js, Nuxt.js など) を使う • 1つの View ライブラリ、1つの言語で UI を実装
  8. 19 Next.js (Pages Router) の挙動 • 全コンポーネントはブラウザ向けの bundle に含まれる ◦

    コンポーネントに書いてあることは、全部漏洩する • コンポーネントに機密情報を書いてはならない
  9. 20 何故コンポーネントがブラウザ向けの bundle に含まれるのか • もしかしたら疑問に思うかも ◦ erb はそうじゃないのに、なんで Next.js

    はそうなるの • コンポーネントはレンダーが1回限りじゃない ◦ サーバー上で1度レンダーされる (SSR) ◦ state が変わったら、ブラウザでもレンダーされる (CSR)
  10. 25 モダンなフロントエンド FW での漏洩対策 • サーバーに機密情報を追いやる • いくつかの実装パターンがある ◦ 1.

    サーバーから機密情報を fetch する ◦ 2. getServerSideProps を使う (Next.js Pages Router 限定) ◦ 3. Server Component を使う (React 限定)
  11. 27 2. getServerSideProps を使う • Next.js Pages Router 限定のテク ◦

    面白いので紹介 • getServerSideProps とは ◦ ページコンポーネント (例: TopPage) に渡す props を生成する関数 • これを使っても漏洩を回避できる
  12. 29 なぜこれで漏洩を回避できるのか • 実は getServerSideProps は... ◦ サーバーサイドで実行される • 関数自体のコードも、サーバーの

    bundle にのみ含まれる ◦ ブラウザの bundle に含まれない • 機密情報を書いても漏洩しない!
  13. 31 3. Server Component (SC) を使う • React 限定のテク •

    React 19 で安定化された、新しい種類のコンポーネント ◦ サーバーで"のみ"レンダーされるコンポーネント ◦ Xslate や erb みたいなやつ • ブラウザの bundle に含まれない ◦ 漏洩を回避できる!
  14. 補足: Client Component (CC) • Server Component の対になるもの • その正体は...

    ◦ SC 登場以前にあったコンポーネントのこと • Server Component 登場によって... ◦ 名前の整理が行われただけ ◦ 今まで書いてたやつが、Client Component と呼ばれるように 32
  15. 補足: 'use client' ディレクティブ • RSC の世界では、デフォルトで SCになる (※1) •

    CC にするには、 ‘use client’ を付ける 33 ※1: 厳密には何もつけないと SC / CC のどちらでもない、未確定の状態になる。 コンポーネント利用側に応じて SC / CC どちらになるか、後から決まる。
  16. 補足: SC と CC の違い 34 Server Components Client Components

    ブラウザの bundle 含まれない 含まれる イベントリスナ ❌ 登録できない ✅ 登録できる サーバ専用 API ✅ 使える ❌ 使えない ブラウザ専用 API ❌ 使えない ✅ 使える React Hooks ❌ 使えない ✅ 使える
  17. 補足: サポート状況 35 • Server Component をサポートしている FW が必要 ◦

    Next.js, Waku, React Router, … ◦ production ready なものは Next.js のみ • Next.js はサポートしているものの... ◦ App Router (新しい Router 実装) でのみサポート ◦ Pages Router (古い Router 実装) では未サポート ▪ コンポーネントはすべて Client Component という扱い
  18. 補足: 他にも色々 36 • SC/CC は入れ子にできる • … • 後は資料見て!!!

    https://speakerdeck.com/mizdra/react-server-components-noyi-wen-wojie-kim ing-kasu
  19. 38 Server Component の落とし穴 • SC => CC に props

    を渡すとき... ◦ 実はその props の中身がユーザから見える
  20. CC に渡す props からの漏洩 • SC から CC に渡した props

    はユーザから丸見え!!! ◦ props が丸ごとシリアライズされ、HTML に埋め込まれてる コードは以下の記事を参考にしつつ、改変してます。 https://zenn.dev/cybozu_frontend/articles/react-taint-apis
  21. 40 CC の props はなぜ HTML に 埋め込まれる? • erb

    で data-initial="<%= count %>" してたのと同じ • サーバーからクライアントにデータを渡すには... ◦ HTML にシリアライズして埋め込まないといけない
  22. 44 調査方法①: grep する • ブラウザ向けのビルド成果物を grep する ◦ 例:

    grep --color -i -r -o -E '機密情報' ./dist • Next.js の場合 ◦ .next/static にブラウザ向けの成果物があるので、そこを grep する
  23. 45 調査方法②: Chrome DevTools の Network パネルを使う • Network パネル

    ◦ ページ閲覧中に発生したリクエストを覗き見れる
  24. 46 調査方法②: Chrome DevTools の Network パネルを使う • 実は検索機能が付いてる ◦

    ページ閲覧中にリクエストされたリソースに対し、平文検索する • これを使えば、機密情報の漏洩を調べられる
  25. 53 ② CC に機密情報が渡るのを Taint API で防ぐ • React に

    Taint API という機能がある ◦ 任意の値を汚染 (taint) できる • 汚染された値を CC に渡すと... ◦ 実行時エラーが発生する • 誤って CC に機密情報を渡してしまうのを防げる
  26. 55 ③ GraphQL で data fetch • 一般的にはレンダーに必要な data を

    fetch するのに... ◦ `prisma.users.findUnique(...)` や `fetch(...)` を使いがち • その代わりに、GraphQL を使う
  27. 56

  28. 57 何が良いの • GraphQL スキーマに書かれた field しか、コンポーネント から触れなくなる ◦ スキーマに書いてない余計なもの

    (User.pass など) は、resolver か ら返される段階で削ぎ落とされる • コンポーネントから余計なものを参照できない ◦ 漏洩もしない • GraphQL の resolver を実装するコストは掛かる... ◦ コストを掛けてでも漏洩リスクを下げたいプロジェクトではアリ
  29. 58 とはいえ • このためだけに GraphQL を利用するのはオーバーキル ◦ resolver の実装コストは無視できない •

    一般にはオススメできないが... ◦ すごく漏洩に気を遣うプロジェクトではアリ
  30. 59 まとめ • モダンなフロントエンド FW では... ◦ (通常) コンポーネントがブラウザから丸見え ◦

    fetch, getServerSideProps, Server Component で漏洩を防ぐ • 漏洩の有無を調べることも大事 ◦ grep, Chrome Devtools • うっかりミスを防ぐのも重要 ◦ CI で grep, Taint API, GraphQL で多層防御
  31. 62 Source Map とは • ビルド前後のコードの対応関係が記録されたファイル ◦ 拡張子は *.map •

    Source Map があることで ◦ スタックトレースがオリジナルのコードのものになる ◦ オリジナルのコードに breakpoint を仕掛けてステップ実行できる
  32. 67 対策 • 本番ビルドでは Source Map を生成しない • とはいえ...どうしても生成したい時はある ◦

    エラー監視サービス (Sentry など) に Source Map を送りたいとか • 以下のようなビルドフローを組むと良い ◦ 1. Source Map 生成ありで本番ビルド ◦ 2. エラー監視サービスに Source Map をアップロード ◦ 3. Source Map を削除 (`rm -rf dist/**/*.map`)
  33. 68 余談 • @sentry/nextjs ◦ ビルド時に Source Map を Sentry

    にアップロードしてくれる ◦ アップロード後、自動で削除もしてくれる • しかし... ◦ 最近まで CSS の Source Map が削除されないバグがあった ◦ https://github.com/getsentry/sentry-javascript/issues/18125 ◦ 5日前に報告して、修正リリース済み
  34. 70 コンポーネントの関連リソースからの漏洩 • 関連リソースとは ◦ コンポーネントファイルから import したり、参照しているもの ◦ CSS,

    画像, JavaScript モジュール • 全部 .next/static 配下に出力される (ブラウザから見れる) • 開発環境用の隠し画像ファイルが漏れるとかはありがち... ◦ 気をつけよう