Skip to content

Security Model ja

Hermes Agent edited this page Oct 1, 2026 · 1 revision

セキュリティモデル

English | 中文 | 日本語 | 한국어 | Español | Português | Русский

browsa は任意の Web コンテンツをモデルへ送り、モデル出力を拡張ページ内で描画し、ユーザーの代理として Cookie 付きリクエストを CDN に送る — セキュリティ境界はすべてこの 3 本のチェーン上に乗る。原則: 「元の成果物を保持する」方向にフェイルオープンし、黙って誤ったデータを作り出すことは決してない。

MV3 CSP とベンダーパッチ

  • 拡張ページの CSP: script-src 'self' 'wasm-unsafe-eval' — new Function/eval は禁止。WASM のインスタンス化は許可。
  • Mol*/RDKit の embind グルーは eval 経由でクラスファクトリを組む → build.mjs がコピー時にベンダーへパッチを当てる(手書きインボーカ。先行初期化は遅延化)。パッチ正規表現は安定した文字列にアンカーし、molstar のアップグレードでマッチしなくなったらビルドが例外で落ちる。
  • 検証環境の教訓: dev-preview はデフォルト CSP が eval を許す素の http ページであり、CSP 違反を捕捉できない。ベンダー交換の後は、実拡張の中で実行し(launchPersistentContext --load-extension、xvfb)、canvas/svg が存在し CSP/EvalError のコンソール出力がゼロであることを表明する。

DOMPurify(モデル出力は敵性入力)

  • ALLOWED_URI_REGEXP を sanitize() オプションとして渡さないこと — DOMPurify はこれを、自身のセーフリストにないすべての許可属性の「値」に適用するため、<ol start="N"> の素の数値を剥がしてしまう(実バグ: 箇条書き番号の破壊)。URI チェックは、明示的な URI_ATTRS 集合にスコープされた uponSanitizeAttribute フックを通す。
  • DOMPurify の data: 許可リストは data:image/svg+xml をカバーしない(スクリプトを運べる)— モジュール読み込み時に 1 回だけ登録されるフックがこれをブロックする。
  • mermaid には securityLevel:'loose' が要る(ノードラベル内の KaTeX)ため、その SVG はベンダー入りの sanitizeMermaidSvg(サニタイズ + 変異描画の拒否)を必ず通す — ロードベアリングなセキュリティ。

最小十分な権限セット

  • <all_urls> host_permissions: 拡張コンテキストの fetch は CORS 免除(Ark / AlphaFold / RCSB / raw.githubusercontent がこれに依存)、DNR が CDN リクエストヘッダを注入し、スクリプトは任意のタブへ注入できる。バックエンドプロキシは存在しないため、これは必要。
  • activeTab は削除済み(サイドパネルからは決して機能しない。注入は明示的な tabId を渡す)。
  • unlimitedStorage: キーフレーム/ページ画像の data URL は履歴の中に置かれる(初回のリクエスト側圧縮まで)— デフォルトの 10MB クォータに実際に達したことが 1 度ある。
  • 拡張の秘密鍵バックアップはリポジトリの外(/root/workspace/browsa-keys/、コミット禁止)。

DNR ヘッダのレシピ(lib/sidepanel/media-headers.js)

ASR のダウンロードには、CDN が受け入れる Referer/Origin/Cookie が要る。セッションスコープの DNR 規則は、CDN ドメイン(bilivideo / googlevideo)+ initiatorDomains: [この拡張の ID] でフィルタし、chrome-extension の Origin をサイト自身のものへ書き換える。両プラットフォームで必要(「YouTube はヘッダ不要、POT は URL の中にある」という仮定は誤りだった — 実機テストで新規ストリームが軒並み 403 した)。

MAIN ワールド抽出: インジェクション防御

ページは、LLM の読者に向けた指示を隠せる。3 層:

  1. <template> 要素と HTML コメントは、Readability がパースする前に剥がされる;
  2. CSS 非表示の要素(display/visibility/opacity/font-size:0/サイズ 0 のボックス)は「生の」ドキュメント上で印を付け、クローンから剥がし、その後印を外す(ページが変異したまま残されることはない)。textContent が空でない要素だけを検査する(コストに上限);
  3. 出力テキストはゼロ幅文字、制御文字、未ペアの UTF-16 サロゲートを剥がす(ペア認識の正規表現 — 一括剥がしは正しい絵文字も殺す)。

chrome.scripting.executeScript がシリアライズするのはちょうど 1 個の関数 — ヘルパーは注入される関数の内側にネストせねばならない(ADR-0009。countImages はモジュールレベルの兄弟関数で、実 Chrome では ReferenceError を投げたが、本体を連結していたテストは何も見えなかった)。

抽出前のページ自動操作(preExtractCleanup)の安全ゲート

  • Cookie 同意のクリック: コンテナゲート + 危険語の拒否(購入/削除/支払い/クリア/リセット … の両言語)。
  • 「続きを読む」の展開: ナビゲーション可能な <a href> は決してクリックしない(実事故: ブランドのリンクが添付の途中でタブを遷移させた)。chrome 領域は除外(nav/aside/[role=…]。GitHub のメガメニューと labuladong の事故の後に硬化)。クリックで開いたダイアログは cancel ラベルの操作で閉じ、そのパスは停止する。
  • lazyload 目的のスクロールはシグナルゲート付き(lazy/virtualized のシグナルが存在するときだけ)。描画抑止は <html> への opacity:0 で行う(visibility は決して使わない — ページ自身のリビール演出が永久に固まることがある)。scrollY は常に復元する。
  • GitHub の /blob/ URL は、ページ自動操作を完全にバイパスする raw 高速パスを取る(開かれたメニューがクローン DOM を汚染した — 実例)。

拡張オリジンの 3 形態(ゲートウェイのオリジン許可リストを作る前に読むこと)

インストール形態 拡張 ID
Chrome Web Store kghjmmajnpbkljankbbjbmnhfdocaeho(CWS 固定)
リポジトリディレクトリからロード(manifest がキーを同梱) apoodheofdhglelbnmggeokbhampbmgn(キーから導出)
リリース zip の展開 パス導出、マシン毎に異なる(パッケージングがキーを剥がす)

chrome://extensions に表示される ID が唯一の真実の源。ローカルゲートウェイは ws:// を使う(wss は拒否される)。ゲートウェイ設定は起動時に 1 回読む。


権威版: Security-Model(英語) / Security-Model-zh(中文) — AI による初翻スナップショット、同期日 2026-10-01。

Clone this wiki locally