Security
セキュリティモデル
任意コード実行を持つリモート制御プラグインを、一般ユーザーに配布できる水準で守るための設計。
なぜ対策が必要か
QGIS Live Driver が提供する pyeval は QGISプロセス内での任意Python実行です。
iface・QgsProject・OS APIにフルアクセスでき、実質的にQGISユーザ権限での
任意コード実行に相当します。対策なしに有効化すると「認証なしのローカルRCEサーバ」が
常駐する形になるため、Driverは既定で無害・有効化はopt-in・全チャネル認証必須
という設計になっています。
防御の全体像
flowchart TB
subgraph ATK["遮断される相手"]
direction TB
A1["外部ネットワーク"]
A2["同一マシンの他OSユーザ"]
A3["ブラウザ内の悪意ページ"]
end
A1 & A2 & A3 -.->|遮断| D1
D1["1. 既定OFF(opt-in有効化)"]
D2["2. 127.0.0.1 バインドのみ"]
D3["3. 全チャネルでセッショントークン必須<br/>(トークンはユーザ限定ACLファイルに保存)"]
D4["4. Host/Origin がloopback以外なら拒否"]
SVC["QGIS Live Driver<br/>pyeval / screenshot / bridge_call ..."]
D1 --> D2 --> D3 --> D4 --> SVC
攻撃者モデル:誰を防ぎ、誰を防がないか
| 相手 | 到達性 | 結果 | 防御手段 |
|---|---|---|---|
| 外部ネットワーク | 不可 | 接続自体が拒否 | 127.0.0.1 へのみバインド。トンネル公開は設計対象外 |
| 同一マシンの他OSユーザ | ポートには届く | トークンを読めず全要求が拒否 | トークンファイル・レジストリにユーザ限定ACL(Windows: icacls / POSIX: chmod 600) |
| ブラウザ内の悪意ページ(ドライブバイ) | no-cors POSTは届く | トークン不在で401/破棄 | 全エンドポイントでトークン照合 + Host/Origin がloopback以外なら403 |
| 同一ユーザ権限の任意プロセス | 届く | 防げない(トークンを読める) | なし — これが脅威モデルの境界(下記) |
各防御層の詳細
1. 既定無害(有効化はopt-in)
インストール直後は何もしません。起動するのは次のどちらかの場合だけです:
WEBENGINE_LIVE_DIR環境変数が設定されている(開発・自動化用)- メニュー
プラグイン > QGIS Live Driver > リモート制御 (localhostのみ)をON (初回は警告ダイアログを表示し、QSettingsに永続化)
OFFの間はHTTPポートもlive dirも作られないため、攻撃面は存在しません。
2. localhost限定
内蔵HTTPサーバは 127.0.0.1 にのみバインドします。LAN/外部からは到達不能です。
ngrok等のトンネル経由でも Host ヘッダがloopback以外になるため403で拒否されます
(外部公開は設計対象外)。
3. セッショントークン(全チャネル必須)
- 起動ごとに
secrets.token_hex(24)で新規生成。使い回しなし - HTTP:
Authorization: Bearer/X-Api-Key/api-keyのいずれか。 無認証は401(例外は/api/healthのみ) - ファイルJSONL:
commands.jsonlの各行に"token"を必須化しhmac.compare_digestで照合。不一致はunauthorizedで破棄 - MCP(/mcp・stdio shim): HTTPと同じ照合
- トークンを知らなければ、ポートを発見しても一切実行できません
4. Host/Origin検証(ブラウザ経由対策)
ブラウザからは fetch(url, {mode:'no-cors'}) でlocalhostへPOSTできます(DNSリバインドや
悪意ページのドライブバイ攻撃)。これに対し Host/Origin が
127.0.0.1/localhost 以外を指す要求は403で拒否します。
トークン必須と合わせた二重の防御です。
5. トークンの保存とACL
トークンは <live_dir>/token とレジストリJSON
(~/.qgis-live/<pid>-qgis_live_driver.json)にのみ保存され、
作成直後にユーザ限定ACLを適用します(Windows: icacls /inheritance:r + /grant:r、
POSIX: chmod 600)。正規クライアント(Harness・mcp_stdio.py・自作ツール)は
ここから自動読み取りするため、利用者がトークンを意識する必要はありません。
脅威モデルの境界(防げないもの)
同一ユーザ権限で動く任意プロセスは防げません。 トークンファイルを読めるため、あなたのアカウントで動くマルウェアには防御不能です。 これはOSの責任範囲であり、あらゆるlocalhostサービスに共通する限界です。 信頼境界はローカルユーザアカウントです。
その他の残存リスク:
pyevalはGUIスレッドで同期実行されるため、重いコードはQGISを固まらせ得る (正当ユーザのみが実行可能だが、運用上の注意点)screenshotは呼び出し側指定パスへPNGを書き込む(トークン保持者のみ)- トークンを外部へ公開・コミットしないこと(扱いはパスワードと同等)
運用上の推奨
- 公開コマンドの絞り込み:
QGIS_LIVE_TOOLSenvでコマンド種別を ホワイトリスト化できる(pyevalを外せば読み取り系のみに限定可能) - 追加キーの併用:
QGIS_LIVE_API_KEYenvを設定すると セッショントークンとは別の固定キーも受理される(自動化で固定認証情報が必要な場合向け) - トンネル公開をしない: Host/Origin検証でそもそも拒否される設計。 外部公開が必要な用途はこのプラグインの対象外
- 自作プラグインを配布する際は プラグイン配布 の 「開発用機構の除去」を参照(Driverは例外で、単体配布が前提の製品)
脆弱性の報告
セキュリティ上の問題を見つけた場合は、公開Issueではなく
GitHubリポジトリ の
メンテナへ個別に連絡してください(リポジトリの SECURITY.md も参照)。