猫の手ツール

Step 2: Browser & Security

11. ブラウザのセキュリティ:
なぜWebサイトは勝手に
ファイルを見られないのか

通常のWebページは、端末内の任意のファイルをパスだけで読むことはできません。画像ツールでは、利用者がファイル選択やドロップで指定したFileを受け取ります。その後にファイルをどこへ送るかは別の実装なので、ブラウザの制限とアプリのデータ処理を分けます。

1. ブラウザはPCの中の「砂場(サンドボックス)」

Webサイトにアクセスしただけで、デスクトップにある大切な写真や、仕事の機密書類が勝手に読み取られたら大変なことになります。JavaScriptはPC上で動作するプログラムですが、通常のアプリケーション(Excelやゲームなど)とは決定的に異なる点があります。

それが、サンドボックス(Sandbox) という仕組みです。通常のWebページはOS全体を自由に操作できず、ブラウザが提供するAPIと権限の範囲で動きます。OSのプロセス隔離、同一オリジンポリシー、ファイル選択の制限などが重なっており、すべてを1つの仕組みで防いでいるわけではありません。

2. ユーザーの「明示的な意思」が壁を壊す

では、なぜ「猫の手ツール」のようなWebアプリで画像を加工したり、ファイルを読み込んだりできるのでしょうか? それは、ユーザーが「このファイルなら見せてもいいよ」と許可を与えた時だけ、一時的にセキュリティの壁に穴が開くからです。

具体的には、<input type="file">をクリックしてファイルを選んだり、画面上にファイルをドラッグ&ドロップしたりする操作がこれにあたります。これらは単なるUIの操作ではなく、ブラウザに対して「この特定のファイルへのアクセス権をJSに渡す」という署名をしているようなものなのです。

コードで見る「権限」の付与

以前のセキュリティ概念が希薄だった時代(あるいはネイティブアプリ)と、現代のWebブラウザの制限を比較してみましょう。

【NG例】もし勝手に読み込めてしまったら(脆弱性)

// ⚠️ 実際には動作しません(セキュリティエラーになります)
const secretData = await fetch('file:///C:/Users/Admin/Desktop/secret.txt');
console.log(secretData); // これができたら世界中のPCが丸裸です。

【正解】ユーザーが許可したファイルだけを扱う

// ユーザーがブラウザのダイアログで「選択」した瞬間
fileInput.onchange = (e) => {
  const file = e.target.files?.[0];
  if (!file) return; // ダイアログをキャンセルした場合
  // fileInput は事前に取得した input type="file" 要素
  const reader = new FileReader();
  
  reader.onload = () => {
    console.log("テキストの読み取りが完了しました"); // 内容を不用意にログへ残さない
  };
  reader.readAsText(file);
};

3. 注意点:初心者がハマりやすい「パス」の勘違い

駆け出しのエンジニアがよく「JavaScriptでPC内の C:\images\photo.jpg を直接読み込みたい」と考えますが、通常のHTTPSページから、そのパスを指定するだけで任意のローカルファイルを読むことはできません。拡張機能や、許可を得て使うファイルシステムAPIは別の権限モデルです。

  • フルパスは隠蔽される: セキュリティ上、JS側からは選択されたファイルのPC内でのフルパス(どのフォルダにいたか)すら取得できません。Fileからは名前、サイズ、MIMEタイプ、更新日時などを取得できます。ファイルの内容も読み取れるため、選択は情報を渡す操作として扱います。
  • 一時的な参照と保存を区別: 通常のファイル選択で得たメモリ上の参照はページの終了で失われます。ただしサイトがIndexedDBへ内容を保存した場合や、ファイルシステムAPIのハンドルを保持した場合は別です。ブラウザ内でどこへ保存する実装かも確認します。
  • ブラウザごとの制限: Chrome、Safari、Firefoxでファイルアクセスの挙動や、対応しているFileSystem APIの範囲が微妙に異なるため、クロスブラウザの検証が必須です。

4. 実務にどう役立っているか

「猫の手ツール」のようなブラウザ完結型のツール開発において、ファイル選択の制限は、利用者が指定した画像だけを扱う設計の土台になります。

選択したFileをサーバーへ送るかどうかはアプリの実装です。サンドボックスが自動的にアップロードを禁止するわけではないため、読み取りと送信を分けて確認します。

画像を選ぶ前と後で変わること

選択前のサイトは、通常、パソコン内の写真一覧を勝手に取得できません。選択後は、そのファイルの内容をJavaScriptで読み取れます。読み取りが可能になった画像を端末内で加工するのか、通信で送るのかは別の判断です。

開発者は、ファイル名・画像内容を不要なログへ出さない、外部スクリプトを管理する、選択キャンセルや読み込み失敗を処理する、といった点まで含めて実装します。利用者向けには「処理する画像の送信」と「広告やライブラリの読み込み通信」を分けて説明すると誤解を減らせます。

画像変換が受け取るのは、選択またはドロップされたFile

画像変換ツールは、input type="file"のfilesか、dropイベントのdataTransfer.filesから先頭のファイルを受け取ります。フォルダー内の別の写真を勝手に列挙するコードではありません。

fileInput.onchange = (event) => {
  const target = event.target;
  if (target.files && target.files[0]) handleFile(target.files[0]);
};

本番の型指定を省いた抜粋です。acceptは選択UIの手掛かりで、ファイルの内容が正しいことを保証する検査ではありません。キャンセル、非対応形式、デコード失敗は次の処理で扱います。画像変換の制作解説とFile APIの読み込みサンプルで、選択後のデータの流れを追えます。

まとめ

私たちが当たり前だと思っている「ファイル選択ボタン」や「ドラッグ&ドロップ」。その裏側では、ブラウザがOSと密接に連携し、ユーザーの許可を厳格に管理しながら、悪意のあるスクリプトからPCを守っています。

この仕組みを理解することは、単に「エラーが出ないコードを書く」だけでなく、「ユーザーに信頼される安全なWebアプリ」を作るための第一歩と言えるでしょう。

参考資料

制作時に確かめたこと