セキュリティ
ブラウザの攻撃面は 2 つに分かれます。私たちが書いていないエンジンと、私たちが書いたシェルです。この 2 つは振る舞いがまったく違うので、分けて説明します。このリリースの既知の欠落はページの最後にあります。
エンジン: Chromium、V8、Skia
2026 年を通じて、Chrome では数十件のメモリ安全性の不具合が修正されました。そのうち 6 件は実際に悪用されたゼロデイです。このコードは私たちが書いているものではなく、修正することもできません。ここでの唯一の防御は、エンジンを最新に保つことです。
だからこそ、私たちのルールははっきりしています。Girginos Browser はサポートの終了した Electron のバージョンではリリースしません。Electron がサポートするのは直近の 3 つのメジャーバージョンだけで、固定しているバージョンはリリースのたびに確認しています。現在は Electron 44.2.0 と Chromium 152.0.7977.76 を使っています。
シェル: 私たちが書いたコード
シェル側の設計上の判断は次のとおりです。
- 各タブは独立した WebContentsView です。ページのコンテンツは sandbox: true、contextIsolation: true、nodeIntegration: false で動作し、preload は渡されません。
- インターフェースのウィンドウもサンドボックスで動作し、タブと同じセッションを共有します。そのためインターフェース自身のリクエストもブロッカーを通り、DNT ヘッダーを伴います。
- IPC のチャンネルは、インターフェースウィンドウのメインフレームからのものだけを受け付けます。設定の書き込みはキーと型の検証を通ります。
- ダウンロードは識別子で参照します。インターフェースから渡された生のファイルパスを開くことはありません。
- ページ側から始まる遷移は http(s) と view-source:http(s) に限られます。file: と chrome: は、利用者が自分でアドレスバーに入力した場合にのみ開きます。
- 外部アプリケーションへの受け渡しは、狭いスキームのリストに限定されています。mailto:、tel:、sms:、magnet:、ftp(s):、webcal: です。確認ダイアログは同時に 1 つしか開きません。
- 不透明なオリジン、つまり data: や about: のように origin が null になるものは、権限の要求に対して常に拒否されます。
- スペルチェックは無効です。Chromium が辞書ファイルを Google のサーバーからダウンロードするためです。
- データは一時ファイルとリネームによって、アトミックに書き込まれます。
攻撃手法と対策
| 分類 | 例 | 対策 |
|---|---|---|
| アドレスバーの偽装 | RLO/bidi, CR-LF, NUL, bank.com@evil.com, 空白による水増し、IDN ホモグラフ | 不可視文字と空白はエンコードしたまま表示し、認証情報は隠し、punycode を表示する |
| ドメイン名の隠蔽 | accounts.google.com.giris.evil.com | 登録可能なドメインを濃く、それ以外を淡く表示する |
| 内部ページのなりすまし | newtab.html, ダウンロードされた複製 | アドレス全体の一致を求め、部分文字列の検索は行わない |
| 全画面でのインターフェース偽装 | ページが全画面になり偽のツールバーを描く | ページのビューをシェルの上まで広げることはしない |
| スキームの逸脱 | file:, chrome:, blob:, view-source:file: | ページ側から始まる遷移は http(s) のみ |
| 外部アプリケーションの呼び出し | ms-msdt:, search-ms:, ms-appinstaller: | 狭い許可リストと、1 つだけの確認ダイアログ |
| ダウンロード名の細工 | evil.exe / evil.exe., 末尾のドットや空白、RLO で隠した拡張子 | 拡張子の判定の前に正規化し、ディスク上の実際の名前で判断する |
| ブロッカーの回避 | izleyici.com., 末尾のドット | ホスト名の正規化 |
署名付きアップデートチェーン
脅威モデルでは、アップデートサーバーがすでに乗っ取られている可能性を前提にしています。手順は次のとおりです。
- 署名済みマニフェストと、その隣にある署名ファイルを取得します。
- アプリケーションに埋め込まれた Ed25519 の公開鍵で、マニフェストの生のバイト列に対して署名を検証します。検証に通らなければ、フィールドは 1 つも読み込みません。
- バージョンのゲートを適用します。ダウングレードは拒否します。マニフェスト自身の有効期限が切れていれば拒否します。これは、古いマニフェストを永久に配り続けてアップデートを凍結させる攻撃への対策です。必要な場合は中間バージョンを必須にします。ダウンロードのアドレスは https でなければなりません。
- ダウンローダーが見つけたバージョンとパッケージのダイジェストは、署名済みマニフェストの値と完全に一致していなければなりません。
- ダウンロードが終わると、パッケージの sha512 ダイジェストを署名済みのダイジェストと定数時間で比較します。
- インストールが始まるのは、利用者が承認したときだけです。
いずれかの手順が失敗すれば、アップデートは行われません。秘密鍵をサーバーに置くことはありません。サーバーが乗っ取られたとしても、攻撃者が有効なマニフェストを作ることはできません。
テスト
118 件のユニットテスト、73 件の攻撃手法に対する回帰テスト、46 件のアップデート検証テストが動いており、インターフェースとメインプロセスの間の IPC と DOM の取り決めも個別にテストしています。それに加えて、リリースの前後には、実際の成果物と稼働中のサーバーに対してエンドツーエンドの検証スクリプトを実行しています。
既知の欠落
以下は 0.1.0 に欠けているものです。隠せば製品を実際より安全に見せてしまうので、はっきり書いておきます。
- Mark-of-the-Web がありません
- ダウンロードしたファイルに Zone.Identifier を書き込まないため、Windows SmartScreen はこれらのファイルに対して働きません。ブラウザ自身の警告ダイアログはありますが、オペレーティングシステムの層がありません。
- コード署名証明書がありません
- インストーラーのコード署名を検証できません。アップデートについては署名済みマニフェストがこれを塞ぎますが、最初のインストールは無防備なままです。
- Public Suffix List がありません
- github.io のようなホスティング用のドメインでは、サイトの例外指定とアドレスバーの強調表示が、本来より広い範囲に及びます。
- 証明書エラーは Chromium の既定のまま
- 独自の「それでも続行」画面は作っていません。証明書に問題があると、ページは開きません。
- ブロックはドメイン単位のみ
- CNAME レコードの裏に隠されたトラッカーや、ファーストパーティから配信される広告は捕捉できません。要素非表示フィルターも適用されません。