Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
機密情報の漏洩を防げ! Webフロントエンド開発で意識すべき漏洩パターンとその対策
Search
mizdra
PRO
November 15, 2025
Technology
1
200
機密情報の漏洩を防げ! Webフロントエンド開発で意識すべき漏洩パターンとその対策
YAPC::Fukuoka 2025 で発表した資料です。
mizdra
PRO
November 15, 2025
Tweet
Share
More Decks by mizdra
See All by mizdra
TypeScript Language Service Plugin で CSS Modules の開発体験を改善する
mizdra
PRO
3
7.8k
あなたの知らない Function.prototype.toString() の世界
mizdra
PRO
4
5.6k
React Server Components の疑問を解き明かす
mizdra
PRO
22
13k
はてなにおける CSS Modules、及び CSS Modules に足りないもの / CSS Modules in Hatena, and CSS Modules missing parts
mizdra
PRO
8
3k
大量の ESLint エラーに対処する技術 / The technology to fight with many ESLint's errors
mizdra
PRO
0
3.2k
Vue Language Server から生まれた Volar.js と、それが秘める可能性
mizdra
PRO
13
9k
マルチテナントで GraphQL を使う際の工夫
mizdra
PRO
0
2.6k
Webフロントエンドの秩序を維持する体制を作る
mizdra
PRO
9
26k
個人開発の裏側
mizdra
PRO
0
380
Other Decks in Technology
See All in Technology
自己的售票系統自己做!
eddie
0
410
Master Dataグループ紹介資料
sansan33
PRO
1
3.9k
ある編集者のこれまでとこれから —— 開発者コミュニティと歩んだ四半世紀
inao
1
170
ubuntu-latest から ubuntu-slim へ移行しよう!コスト削減うれしい~!
asumikam
0
460
マーケットプレイス版Oracle WebCenter Content For OCI
oracle4engineer
PRO
3
1.3k
エンジニア採用と 技術広報の取り組みと注力点/techpr1112
nishiuma
0
130
LINE公式アカウントの技術スタックと開発の裏側
lycorptech_jp
PRO
0
340
Snowflakeとdbtで加速する 「TVCMデータで価値を生む組織」への進化論 / Evolving TVCM Data Value in TELECY with Snowflake and dbt
carta_engineering
2
240
マウントとるやつ、リリースするやつ
otsuki
1
110
手を動かしながら学ぶデータモデリング - 論理設計から物理設計まで / Data modeling
soudai
PRO
5
2k
【Android】テキスト選択色の問題修正で心がけたこと
tonionagauzzi
0
130
Flutterで実装する実践的な攻撃対策とセキュリティ向上
fujikinaga
1
310
Featured
See All Featured
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
2.6k
Context Engineering - Making Every Token Count
addyosmani
9
370
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
2.9k
Embracing the Ebb and Flow
colly
88
4.9k
Designing for Performance
lara
610
69k
For a Future-Friendly Web
brad_frost
180
10k
Bootstrapping a Software Product
garrettdimon
PRO
307
110k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
5.7k
How STYLIGHT went responsive
nonsquared
100
5.9k
Site-Speed That Sticks
csswizardry
13
960
Gamification - CAS2011
davidbonilla
81
5.5k
How to Ace a Technical Interview
jacobian
280
24k
Transcript
機密情報の漏洩を防げ! Webフロントエンド開発で 意識すべき漏洩パターンとその対策 id:mizdra 2025/11/15 YAPC::Fukuoka 2025 1
自己紹介 • mizdra (みずどら) • インターネット大好き • 株式会社はてな ◦ フロントエンドエキスパート
◦ 社内のフロントエンド啓発活動 2
3 今日のテーマ Web フロントエンドにおける 機密情報の漏洩対策
4 機密情報 • 機密情報と言っても色々ある ◦ 個人情報 (メールアドレス, 住所) ◦ 業務上の情報
(開発環境のドメイン, 未公開のキャンペーン情報) ◦ 認証情報 (API トークン, Cookie) ◦ ログ (アクセスログ、アプリケーションログ) ◦ ソースコード • 要は漏れるとマズいもの
5 Web フロントエンドにおいては • 漏れないように注意して開発しようという話ではある • ただし Web フロントエンドフロントエンドでは... ◦
機密情報の漏洩が起きやすい • 何故か ◦ ユーザに面してる ◦ HTML や JavaScript がブラウザから読める • 見える情報が多いゆえに脆弱
6 最近の Web フロントエンドは 落とし穴が結構ある • モダンなフロントエンドフレームワークでは... ◦ 機密情報を漏洩させやすいポイントがある •
フレームワークの裏側の挙動を知ってれば回避可能だが... ◦ 知らないとハマる ◦ テンプレートエンジン (Xslate, erb) に慣れてる人ほどハマりやすい
7 このセッションの目的 モダンな Web フロントエンド開発で漏洩を防ぐための知識 と術を伝えます。 • 従来技術 (Xslate, erb)
との違い ◦ なぜモダンなフロントエンド FW は漏洩させやすいのか ◦ 漏洩を防ぐにはどうしたら良いのか • 漏洩の有無を調べる方法 • うっかり漏洩するのを防ぐテクニック
8 おことわり • React, Next.js の話が割と多め • とはいえ他の View ライブラリ/FW
に適用可能な話もある • 最もメジャーな流派の事情を知るのは良いこと
9 従来技術との違い
10 従来技術とは • ここでいう従来技術というのは... ◦ Xslate (Perl), erb (Ruby), PHP
◦ いわゆるテンプレートエンジン • リクエストが来たら、サーバでテンプレートをレンダー ◦ HTML を返す
例: erb で Counter を作る
12 最近の Web フロントエンド開発 • JS の View ライブラリを使って UI
を組むのが主流 ◦ React, Vue.js, Angular, … • ブラウザ上でコンポーネントをレンダーするだけでなく ◦ SSR (サーバー上でレンダー) するのが当たり前 ◦ SSR をサポートする FW (Next.js, Nuxt.js など) を使う • 1つの View ライブラリ、1つの言語で UI を実装
例: Next.js (Pages Router) で Counter 13
14 erb と違い、テンプレートは不要。 JavaScript のコードだけあれば良い。 例: Next.js (Pages Router) で
Counter
15 機密情報の漏洩度合いが違う • より綺麗な形で従来技術と同じことができるが... ◦ 完全に同じだと思ってると、痛い目を見る • 実はモダンなフロントエンド FWでは... ◦
機密情報の漏洩度合いが高まってる
期間限定のキャンペーン情報を出す (erb) 16 お正月になってたら表示される、みたいなやつ
17 Next.js (Pages Router) で同じことを やってみる
18 Next.js (Pages Router) の場合 • 実はキャンペーン情報が漏洩してる ◦ お正月前に、キャンペーンが存在することが分かってしまう
19 Next.js (Pages Router) の挙動 • 全コンポーネントはブラウザ向けの bundle に含まれる ◦
コンポーネントに書いてあることは、全部漏洩する • コンポーネントに機密情報を書いてはならない
20 何故コンポーネントがブラウザ向けの bundle に含まれるのか • もしかしたら疑問に思うかも ◦ erb はそうじゃないのに、なんで Next.js
はそうなるの • コンポーネントはレンダーが1回限りじゃない ◦ サーバー上で1度レンダーされる (SSR) ◦ state が変わったら、ブラウザでもレンダーされる (CSR)
再掲: Next.js Pages Router で Counter 21
22 何故コンポーネントがブラウザ向けの bundle に含まれるのか • ブラウザでレンダーするには... ◦ ブラウザが、コンポーネントのコードを持ってないといけない • そのため...
◦ 全てのコンポーネントが、ブラウザ向けの bundle に含まれる
23 伝えたかったこと • テンプレートとコンポーネント、同じように見えるが... ◦ 漏洩の度合いが違う ◦ コンポーネントは全部ブラウザの bundle に含まれる
• コンポーネントには機密情報を書いてはならない
24 モダンなフロントエンド FW での漏洩対策
25 モダンなフロントエンド FW での漏洩対策 • サーバーに機密情報を追いやる • いくつかの実装パターンがある ◦ 1.
サーバーから機密情報を fetch する ◦ 2. getServerSideProps を使う (Next.js Pages Router 限定) ◦ 3. Server Component を使う (React 限定)
26 1. サーバーから機密情報を fetch する Next.js 以外の FW でもできる 最も手軽な回避策
27 2. getServerSideProps を使う • Next.js Pages Router 限定のテク ◦
面白いので紹介 • getServerSideProps とは ◦ ページコンポーネント (例: TopPage) に渡す props を生成する関数 • これを使っても漏洩を回避できる
28 例: getServerSideProps を使った回避策
29 なぜこれで漏洩を回避できるのか • 実は getServerSideProps は... ◦ サーバーサイドで実行される • 関数自体のコードも、サーバーの
bundle にのみ含まれる ◦ ブラウザの bundle に含まれない • 機密情報を書いても漏洩しない!
30 例: getServerSideProps を使った回避策 サーバーの bundle に含まれる ブラウザの bundleに含まれる
31 3. Server Component (SC) を使う • React 限定のテク •
React 19 で安定化された、新しい種類のコンポーネント ◦ サーバーで"のみ"レンダーされるコンポーネント ◦ Xslate や erb みたいなやつ • ブラウザの bundle に含まれない ◦ 漏洩を回避できる!
補足: Client Component (CC) • Server Component の対になるもの • その正体は...
◦ SC 登場以前にあったコンポーネントのこと • Server Component 登場によって... ◦ 名前の整理が行われただけ ◦ 今まで書いてたやつが、Client Component と呼ばれるように 32
補足: 'use client' ディレクティブ • RSC の世界では、デフォルトで SCになる (※1) •
CC にするには、 ‘use client’ を付ける 33 ※1: 厳密には何もつけないと SC / CC のどちらでもない、未確定の状態になる。 コンポーネント利用側に応じて SC / CC どちらになるか、後から決まる。
補足: SC と CC の違い 34 Server Components Client Components
ブラウザの bundle 含まれない 含まれる イベントリスナ ❌ 登録できない ✅ 登録できる サーバ専用 API ✅ 使える ❌ 使えない ブラウザ専用 API ❌ 使えない ✅ 使える React Hooks ❌ 使えない ✅ 使える
補足: サポート状況 35 • Server Component をサポートしている FW が必要 ◦
Next.js, Waku, React Router, … ◦ production ready なものは Next.js のみ • Next.js はサポートしているものの... ◦ App Router (新しい Router 実装) でのみサポート ◦ Pages Router (古い Router 実装) では未サポート ▪ コンポーネントはすべて Client Component という扱い
補足: 他にも色々 36 • SC/CC は入れ子にできる • … • 後は資料見て!!!
https://speakerdeck.com/mizdra/react-server-components-noyi-wen-wojie-kim ing-kasu
37 Server Component で漏洩を回避する例 (詳細は割愛するが) Next.js では app/page.tsx が Server
Component なので、ここに書いたら良い
38 Server Component の落とし穴 • SC => CC に props
を渡すとき... ◦ 実はその props の中身がユーザから見える
CC に渡す props からの漏洩 • SC から CC に渡した props
はユーザから丸見え!!! ◦ props が丸ごとシリアライズされ、HTML に埋め込まれてる コードは以下の記事を参考にしつつ、改変してます。 https://zenn.dev/cybozu_frontend/articles/react-taint-apis
40 CC の props はなぜ HTML に 埋め込まれる? • erb
で data-initial="<%= count %>" してたのと同じ • サーバーからクライアントにデータを渡すには... ◦ HTML にシリアライズして埋め込まないといけない
41 対策: 必要なプロパティだけ渡す pass などの機密情報は除外
42 漏洩の有無を調べる方法
43 漏洩の有無を調べる • 漏洩対策を実施するだけでなく... ◦ 本当に漏洩が起きてないか確認することも重要 • 調査のためのテクニックをいくつか紹介
44 調査方法①: grep する • ブラウザ向けのビルド成果物を grep する ◦ 例:
grep --color -i -r -o -E '機密情報' ./dist • Next.js の場合 ◦ .next/static にブラウザ向けの成果物があるので、そこを grep する
45 調査方法②: Chrome DevTools の Network パネルを使う • Network パネル
◦ ページ閲覧中に発生したリクエストを覗き見れる
46 調査方法②: Chrome DevTools の Network パネルを使う • 実は検索機能が付いてる ◦
ページ閲覧中にリクエストされたリソースに対し、平文検索する • これを使えば、機密情報の漏洩を調べられる
47 使い方
48 注意 • ここでの検索対象は... ◦ 実際にブラウザでリクエストされたリソースだけ ◦ リクエストされなかったリソースは検索対象にならない • 本当は漏洩しているのだけど...
◦ Network パネルの検索で見つからないことがある
49 Network パネルの検索で見つけられない例
50 うっかり漏洩を防ぐ テクニック
51 うっかり漏洩するのを防ぐ • 漏洩対策を心がけていても... ◦ うっかり対策が忘れられて漏れることも • 万が一不備があっても漏れない・漏れを検知できると良い ◦ テクニックを3つ紹介
52 ① CI で grep する シンプルだけど、これが一番効く!
53 ② CC に機密情報が渡るのを Taint API で防ぐ • React に
Taint API という機能がある ◦ 任意の値を汚染 (taint) できる • 汚染された値を CC に渡すと... ◦ 実行時エラーが発生する • 誤って CC に機密情報を渡してしまうのを防げる
例: Taint API で user.pass を汚染する コードは以下の記事を参考にしつつ、改変してます。 https://zenn.dev/cybozu_frontend/articles/react-taint-apis user.pass を汚染
(taint) する
55 ③ GraphQL で data fetch • 一般的にはレンダーに必要な data を
fetch するのに... ◦ `prisma.users.findUnique(...)` や `fetch(...)` を使いがち • その代わりに、GraphQL を使う
56
57 何が良いの • GraphQL スキーマに書かれた field しか、コンポーネント から触れなくなる ◦ スキーマに書いてない余計なもの
(User.pass など) は、resolver か ら返される段階で削ぎ落とされる • コンポーネントから余計なものを参照できない ◦ 漏洩もしない • GraphQL の resolver を実装するコストは掛かる... ◦ コストを掛けてでも漏洩リスクを下げたいプロジェクトではアリ
58 とはいえ • このためだけに GraphQL を利用するのはオーバーキル ◦ resolver の実装コストは無視できない •
一般にはオススメできないが... ◦ すごく漏洩に気を遣うプロジェクトではアリ
59 まとめ • モダンなフロントエンド FW では... ◦ (通常) コンポーネントがブラウザから丸見え ◦
fetch, getServerSideProps, Server Component で漏洩を防ぐ • 漏洩の有無を調べることも大事 ◦ grep, Chrome Devtools • うっかりミスを防ぐのも重要 ◦ CI で grep, Taint API, GraphQL で多層防御
60 おまけ
61 よくある漏洩パターン ① Source Map の漏洩
62 Source Map とは • ビルド前後のコードの対応関係が記録されたファイル ◦ 拡張子は *.map •
Source Map があることで ◦ スタックトレースがオリジナルのコードのものになる ◦ オリジナルのコードに breakpoint を仕掛けてステップ実行できる
63 Source Map の例 コードは https://web.dev/articles/source-maps?hl=ja より引用
64 Source Map の例 コードは https://web.dev/articles/source-maps?hl=ja より引用 ビルド前後の対応関係が圧縮されて格納されてる
65 Source Map の例 コードは https://web.dev/articles/source-maps?hl=ja より引用 オリジナルのコードが含まれてる
66 Source Map が漏れた場合 • sourcesContent も漏洩してしまう • => オリジナルのコードが漏れるのと同じことに
67 対策 • 本番ビルドでは Source Map を生成しない • とはいえ...どうしても生成したい時はある ◦
エラー監視サービス (Sentry など) に Source Map を送りたいとか • 以下のようなビルドフローを組むと良い ◦ 1. Source Map 生成ありで本番ビルド ◦ 2. エラー監視サービスに Source Map をアップロード ◦ 3. Source Map を削除 (`rm -rf dist/**/*.map`)
68 余談 • @sentry/nextjs ◦ ビルド時に Source Map を Sentry
にアップロードしてくれる ◦ アップロード後、自動で削除もしてくれる • しかし... ◦ 最近まで CSS の Source Map が削除されないバグがあった ◦ https://github.com/getsentry/sentry-javascript/issues/18125 ◦ 5日前に報告して、修正リリース済み
69 よくある漏洩パターン ② コンポーネントの 関連リソースからの漏洩
70 コンポーネントの関連リソースからの漏洩 • 関連リソースとは ◦ コンポーネントファイルから import したり、参照しているもの ◦ CSS,
画像, JavaScript モジュール • 全部 .next/static 配下に出力される (ブラウザから見れる) • 開発環境用の隠し画像ファイルが漏れるとかはありがち... ◦ 気をつけよう