「ファイルを送信しない」Webツールを利用者側から確かめる方法を解説。Chrome DevToolsのNetwork、オフライン動作、CSPを組み合わせ、確認できる事実と限界を整理します。
目次(8)
PDF変換、画像圧縮、Markdownプレビュー、文字起こし。
最近は「ブラウザだけで処理」「ファイルをサーバーへ送信しません」と書かれたオンラインツールをよく見かけます。
自分でもそうしたツールを作っているので、この言葉はかなり気になります。
ただ、利用者側から見ると一つ問題があります。
「送信しません」と書いてあることと、本当に送信されていないことは別です。
プライバシーポリシーを読んでも、実装までは見えません。逆に、ブラウザで動いているからといって必ずサーバーへ送っているわけでもありません。File APIやWebAssemblyを使えば、ファイルの読み込みから変換まで端末内で完結できます。
では、利用者自身が「このファイルはどこへ行っているのか」を確認する方法はあるのでしょうか。
調べながら自分のツールでも試してみると、Chrome DevToolsのNetworkを見るだけでもかなり分かります。ただし、それだけで「絶対に何も送信できない」と証明できるわけではありませんでした。
先に結論:見るべきなのは「実際の通信」と「許可されている通信」の両方
オンラインツールを確認するときは、次の3つを分けて考えると整理しやすくなります。
Networkパネルは、その操作中に実際に何が通信されたかを見るためのものです。
オフラインテストは、その処理がリモートサーバーなしでも成立するかを見る補助材料です。
Content-Security-Policy(CSP)は、ブラウザ側でどこへの通信が許可されているかを確認する材料です。
Networkは観測、CSPは制約、オフラインテストは補助証拠です。
どれか一つだけで「完全に安全」と言うのではなく、実際の挙動と構造を重ねて判断するのが現実的です。
参考:Chrome DevTools: Network panel
まずは「実際に何が通信されたか」を見る
一番分かりやすいのがChrome DevToolsのNetworkパネルです。
ファイルを選ぶ前にNetworkを開く
Chromeでは、ページを開いた状態でDevToolsを起動し、Networkを選びます。
Windowsなら F12 や Ctrl + Shift + I、Macなら Command + Option + I などで開けます。
重要なのは、確認したい操作より先にNetworkパネルを開くことです。
NetworkはDevToolsを開いている間のリクエストを記録します。そこで、
- ツールを開く
- Networkを開く
- ログをクリアする
- ファイルを選ぶ
- 変換・プレビューなどの処理を実行する
- その瞬間に増えた通信を見る
という順で確認します。
ページを開いただけでも、JavaScript、フォント、アクセス解析などの通信が発生することがあります。
知りたいのは、ファイルを選んだ瞬間や処理ボタンを押した瞬間に何が増えたかです。
Fetch/XHRだけではなく、Allで見る
ファイルアップロードなら fetch() や XMLHttpRequest が使われることは多いので、Fetch/XHRで絞るのは有効です。
ただし、それだけを見て「送信されていない」と判断するのは早すぎます。
通信経路にはWebSocket、Beacon、画像、フォーム送信などもあります。
例えばMarkdownに、

という外部画像が含まれていたとします。
ツールがMarkdown本文そのものをAPIへ送っていなくても、画像を表示するために example.com へHTTPリクエストが出る可能性があります。
つまり、「本文をアップロードしていない」と「外部通信が一切ない」は別です。
確認時はNetworkをAllにして、全体を見る方が安全です。
怪しい通信があれば、送信先・Payload・Initiatorを見る
リクエストを選択すると、ChromeではHeaders、Payload、Response、Initiator、Timingなどを確認できます。
特に見たいのは、
- どのドメインへ送っているか
- POSTなどで何を送っているか
- どの処理が通信を開始したか
です。
ファイルを選んだ瞬間に未知のAPIへPOSTが発生し、Payloadにファイルデータが含まれているなら、少なくとも「ブラウザ内だけで処理している」とは言えません。
一方、通信があること自体が直ちに危険という意味でもありません。
アクセス解析、エラーログ、Webフォント、WebAssemblyファイル、AIモデルの初回ダウンロードなど、ファイル本文とは関係のない通信もあります。
重要なのは、通信の有無ではなく、何を・どこへ・いつ送っているかです。
参考:Chrome DevTools: Network features reference
次に「ネットがなくても処理できるか」を試す
Networkで実通信を確認した後、処理場所のヒントになるのがオフラインテストです。
オフラインで最後まで動けば、ローカル処理の材料にはなる
Chrome DevToolsではネットワーク条件をOfflineへ切り替えられます。
一度ページと必要なリソースを読み込んだあと、Offlineにして同じファイル処理を試します。
例えばMarkdown変換や画像圧縮がオフラインでも最後まで動くなら、少なくともその処理を完了するために毎回リモートサーバーへ問い合わせる必要はない可能性が高くなります。
ただし、これも証明ではありません。
Service Workerやキャッシュに必要なデータが残っているかもしれません。オンライン時だけ利用ログを送る実装もあり得ます。
逆に、初回だけWebAssemblyやAIモデルをダウンロードするツールは、初回オフラインでは起動できなくても、ユーザーファイル自体は外部へ送っていない場合があります。
オフラインで動く=オンライン時にも通信ゼロではありません。
もう一段見るなら「通信できる範囲」をCSPで確認する
Networkで「今は送っていなかった」ことを確認できても、実装上は送れる状態かもしれません。
そこで見る価値があるのがContent-Security-Policyです。
connect-src はJavaScriptからの外向き通信を制限する
CSPは、Webページがどこからスクリプトや画像を読み込めるか、JavaScriptがどこへ接続できるかなどをブラウザ側で制限します。
例えば、
Content-Security-Policy: connect-src 'none'
と設定されていれば、CSPの対象となるJavaScript通信は許可されません。
MDNによると connect-src は、fetch()、XMLHttpRequest、WebSocket、EventSource、Navigator.sendBeacon() などの接続先を制限します。
これは「通信しません」と説明文に書くこととは性格が違います。
JavaScriptが通信しようとしても、ポリシーに反すればブラウザ自身が止めるからです。
実際に作ってみると、connect-src 'none' だけでは足りなかった
ここは自分でMarkdown Viewerを作ったときに実際に引っかかった部分です。
最初はAPI通信を止めれば十分だと考えていました。
ところが監査すると、画像について https: からの読み込みを許可していました。
つまり fetch() などを止めても、Markdown内に外部画像URLがあれば、その画像を取得する通信経路が残ります。
そこで現在は img-src も制限し、外部画像をそのまま読み込まない構成に変更しています。
この経緯は、ブラウザ完結ツールの「送信しない」を、約束ではなく構造にするにも残しています。
CSPでは、connect-src 以外にも img-src、media-src、font-src、frame-src、form-action など、通信や読み込みの種類ごとに制御があります。
そのため、一つのディレクティブだけを見て「外向き通信は完全に不可能」と断定するべきではありません。
default-src 'none' から必要なものだけ許可する方が読みやすい
CSPを読むとき、個人的に分かりやすいのがdeny-by-default型です。
Content-Security-Policy:
default-src 'none';
script-src 'self';
style-src 'self';
img-src 'self' data:;
のように、最初に原則禁止し、必要な種類だけ許可します。
この方が「書き忘れた種類が暗黙に自由になる」状態を減らしやすくなります。
ただし、CSPはWebセキュリティ全体を解決する仕組みではありません。
ブラウザ拡張や端末のマルウェアまで止めるものではなく、「このPCから一切情報が外へ出ない」ことを数学的に証明する機能でもありません。
CSPは強い構造的な証拠にはなるが、万能な安全証明ではないという位置づけが妥当です。
参考:MDN: Content Security Policy
調査するときに間違えやすいポイント
NetworkやCSPを見ればかなり判断材料は増えますが、誤判定しやすい点もあります。
ブラウザ拡張の通信を、サイト自身の通信と勘違いする
広告ブロッカー、パスワードマネージャー、翻訳、AIアシスタントなどの拡張機能が、ページへスクリプトを挿入したり独自の通信をしたりすることがあります。
厳密に確認したい場合は、拡張機能を無効にした新しいブラウザプロファイルなどで試す方が切り分けやすくなります。
「知らないドメインがある=そのツールが送った」と即断しないことも重要です。
「通信ゼロ」と「安全」を同じ意味にする
仮に外部通信が完全にゼロでも、そのツールが安全とは限りません。
ファイルを壊すバグがあるかもしれません。生成結果が意図と違うかもしれません。悪意ある入力でブラウザが重くなる可能性もあります。
ローカル処理で減らせるのは、処理のために第三者サーバーへデータを渡すという一つのリスクです。
セキュリティ全体の保証とは分ける必要があります。
自分で確認できても、組織の利用ルールは別
契約書、コード、未公開原稿、顧客データなどを扱う場合、Networkを確認して問題が見えなかったから自由に使ってよい、ということにはなりません。
会社や組織のセキュリティポリシー、利用許可、データ分類のルールがあれば、それが優先されます。
実際に確認するなら、この順番が分かりやすい
開発者でなくても、最低限次の順番なら確認できます。
- DevToolsのNetworkを開いてログを消す
- ファイルを読み込ませ、処理直後に増えた通信を見る
- 外部ドメインへのPOSTやPayloadを確認する
- Offlineにして同じ処理が成立するか試す
- Response HeadersのCSPを確認し、
connect-srcやimg-srcなどを見る
この5段階で完全な監査ができるわけではありません。
それでも、「プライバシーポリシーにそう書いてあるから信じる」状態からはかなり前へ進めます。
よくある質問
Networkパネルはいつ開けばいい?
確認したい操作より先に開きます。Networkは開いている間のリクエストを記録するので、ログをクリアしてからファイルを選び、その瞬間に増えた通信を見ます。
Fetch/XHRに何もなければ送信されていないと言える?
早すぎます。通信経路にはWebSocket、Beacon、画像、フォーム送信などもあり、Markdown内の外部画像URLだけでもリクエストは出ます。NetworkはAllにして全体を見る方が安全です。
オフラインで動けばローカル処理と断定できる?
証明にはなりません。Service Workerやキャッシュに必要なデータが残っていたり、オンライン時だけ利用ログを送る実装もあり得ます。オフラインで動くことと、オンライン時に通信ゼロであることは別です。
CSPに connect-src 'none' があれば外部へは何も送れない?
connect-src は fetch() や XMLHttpRequest などJavaScriptからの接続先を制限しますが、img-src などが緩ければ外部画像の取得経路は残ります。一つのディレクティブだけで「外向き通信は完全に不可能」と断定すべきではありません。
知らないドメインへの通信があれば、そのツールが送っている?
即断はできません。広告ブロッカーやパスワードマネージャーなどブラウザ拡張が独自の通信をすることがあります。厳密に確認するなら、拡張機能を無効にした新しいプロファイルで試す方が切り分けやすくなります。
「送信しません」は、宣言より検証できる構造の方が強い
最初は、サービス提供者が「ファイルを送信しません」と言えば、利用者はそれを信じるしかないと思っていました。
実際にはそうでもありません。
Networkを見れば、その操作中に発生した通信を確認できます。
Offlineにすれば、処理にネットワークが必須か試せます。
CSPを見れば、JavaScriptや画像などにどんな通信先が許可されているか確認できます。
もちろん完全な証明ではありません。
それでも、宣言しかない状態と、利用者自身が挙動と制約を確認できる状態ではかなり違います。
自分でブラウザ完結ツールを作る側としても、ここは重要だと思っています。
「データを送りません」と書くだけではなく、Networkを見れば実際に送っていない。さらにCSPを見れば、外へ通信しようとしてもブラウザ側で制約がかかる。
Webツールのプライバシーは、説明文だけでなく観測できる挙動と、検証できる構造でも示せる。
今回調べてみて、一番大きかったのはそこでした。