権限と Capabilities
プラグインやリモート URL を含め、フロントエンドがアクセスできる内容を制御する Tauri v2 Capabilities の設定。
Capabilities とは何か
Tauri v2 はフロントエンド(WebView)が何を許可されているかを制御する Capabilities システムを使用する。すべての IPC コマンドがデフォルトでアクセス可能だった Tauri v1 とは異なり、Tauri v2 は明示的な権限付与を必要とする。
Capabilities は Tauri プロジェクトの capabilities/ ディレクトリ下の JSON ファイルで定義する。
デフォルトの Capability ファイル
典型的な capabilities/:
{
"identifier": "default",
"windows": ["main"],
"remote": {
"urls": ["http://localhost:*/**"]
},
"permissions": ["core:default", "dialog:default", "shell:default"]
}identifier
この Capability セットの一意な名前。異なるセキュリティコンテキスト用に複数の Capability ファイルを持つことができる。
windows
この Capability が適用されるウィンドウ。["main"] は、ラベルが "main" のウィンドウのみがこれらの権限を取得することを意味する。追加のウィンドウ(例:設定、About)を作成する場合、そのラベルをここに含めるか、別の Capability ファイルを作成する必要がある。
remote
どのリモート URL が Tauri IPC ブリッジにアクセスできるかを制御する。開発時には特に重要である:
"remote": {
"urls": ["http://localhost:*/**"]
}これにより、任意の localhost URL(任意のポート、任意のパス)が Tauri コマンドを invoke できる。これがなければ、Vite 開発サーバーは Rust バックエンドと通信できない。
Note
本番環境ではフロントエンドは tauri: URL から読み込まれ、常に IPC アクセスが可能である。remote セクションは主にローカル開発サーバーとの開発用である。
permissions
フロントエンドに付与される権限のリスト。各権限は特定のプラグインまたはコア機能にスコープされている。
コア権限
core:default
基本的な Tauri 機能を有効にするベースライン権限である:
IPC コマンド呼び出し(
generate_handler!に登録されたコマンド用)イベントシステム(
emit、listen)ウィンドウ管理の基本機能
core:default がなければ、フロントエンドは Tauri コマンドを一切呼び出せない。
プラグイン権限
各 Tauri プラグインは独自の権限スコープを定義する。明示的に付与する必要がある。
dialog:default
ネイティブダイアログ API(ファイルピッカー、フォルダピッカー、メッセージボックス)を有効にする:
// Rust side: requires dialog plugin
app.dialog().file().blocking_pick_folder()// Frontend side: requires dialog:default permission
import { open } from "@tauri-apps/plugin-dialog";
const selected = await open({ directory: true });プラグインの登録が必要:
tauri::Builder::default()
.plugin(tauri_plugin_dialog::init())shell:default
デフォルトブラウザで URL を開くなどのシェル操作を有効にする:
// Rust side: requires shell plugin
tauri::Builder::default()
.plugin(tauri_plugin_shell::init())// Frontend side: requires shell:default permission
import { open } from "@tauri-apps/plugin-shell";
await open("https://example.com");Warning
shell:default 権限は、フロントエンドが URL を開いたりシェルコマンドを実行したりすることを許可する。セキュリティに敏感なアプリケーションでは、default の代わりにより制限的なシェル権限の使用を検討する。
新しい権限の追加
新しい Tauri プラグインを追加する際は、以下を行う必要がある:
Cargo.tomlにプラグインを追加するmain.rsで.plugin()を使って登録するcapabilities/にプラグインの権限を追加するdefault. json
例えば、クリップボードプラグインを追加する場合:
{
"permissions": [
"core:default",
"dialog:default",
"shell:default",
"clipboard-manager:default"
]
}Info
プラグインを追加しても権限の追加を忘れた場合、そのプラグインの API へのフロントエンド呼び出しはサイレントに失敗するか、ランタイムで権限エラーをスローする。コンパイル時チェックは存在しない。
セキュリティ:CSP 設定
Tauri v2 は WebView が読み込めるものを制限するための Content Security Policy (CSP) ヘッダーをサポートする。tauri.conf.json 内で設定する:
{
"app": {
"security": {
"csp": "default-src 'self'; script-src 'self'"
}
}
}CSP を null に設定するとすべての CSP 制限が無効になる:
{
"app": {
"security": {
"csp": null
}
}
}Warning
"csp": null を設定すると Content Security Policy が完全に無効になる。これは WebView があらゆるオリジンからスクリプト、スタイル、リソースを読み込めることを意味する。セキュリティ上の影響を理解しており、アプリが機密データを扱わない場合にのみ行う。
開発時には、Vite 開発サーバーがホットリロードスクリプトを注入するため、緩和された CSP が必要になることが多い。本番環境では、厳格な CSP を設定すべきである。
複数の Capability ファイル
異なるセキュリティコンテキスト用に別々の Capability ファイルを作成できる:
capabilities/
default. json # Main window permissions
settings. json # Settings window (restricted)// capabilities/settings.json
{
"identifier": "settings",
"windows": ["settings"],
"permissions": ["core:default"]
}これにより設定ウィンドウにはコア権限のみが付与され、ダイアログ、シェル、その他のプラグインへのアクセスは与えられない。
プラットフォームスコープの Capabilities
Capability ファイルは "platforms" フィールドで特定のプラットフォームにスコープを限定できる。これにより、利用できるネイティブ API が異なるデスクトップとモバイルとで、単一のプロジェクトが異なる権限を付与できる。
// capabilities/default.json — desktop
{
"identifier": "default",
"platforms": ["macOS", "windows", "linux"],
"windows": ["main"],
"remote": {
"urls": ["http://localhost:*/**"]
},
"permissions": [
"core:default",
"dialog:default",
"shell:default",
"haptics:default",
"notification:default"
]
}// capabilities/ios.json — iOS
{
"identifier": "ios",
"platforms": ["iOS"],
"windows": ["main"],
"permissions": ["core:default", "dialog:default"]
}// capabilities/android.json — Android
{
"identifier": "android",
"platforms": ["android"],
"windows": ["main"],
"permissions": ["core:default", "dialog:default"]
}デスクトップ用ファイルは shell:default、haptics:default、notification:default に加えて開発サーバー用の remote.urls を付与する。ios.json は 意図的に shell:default を省略している:iOS はサンドボックス内にプロセス起動や PTY の API を持たないため、ここでシェル権限を付与しても存在し得ない機能へのアクセスを与えることになる。
haptics:default と notification:default がデスクトップ用ファイルにも含まれているのは、これらのプラグインがすべてのプラットフォームで登録されるためである。デスクトップではハプティック呼び出しは単に無音のノーオペレーションになる(ハプティックハードウェアが存在しない)が、それでも権限を付与しておかないと、Capability レイヤーで IPC 呼び出しが拒否されてしまう。
多層防御:一致しなければならない 2 つのレイヤー
iOS の Capability から shell:default を外すのは話の半分にすぎない。Rust 側もコンパイル時に同じことを行い、この 2 つのレイヤーは一致していなければならない。
// main.rs — the shell plugin is not even compiled on iOS
let builder = tauri::Builder::default()
.plugin(tauri_plugin_dialog::init())
.plugin(tauri_plugin_haptics::init())
.plugin(tauri_plugin_notification::init());
// No PTY / process-spawning API exists in the iOS sandbox, so the
// shell plugin is excluded from the build entirely on that target.
#[cfg(not(target_os = "ios"))]
let builder = builder.plugin(tauri_plugin_shell::init());レイヤー 1(Capability):
ios.jsonはshell:defaultを省略しているため、Tauri の権限システムが Capability レベルでシェル呼び出しをブロックする。レイヤー 2(Rust ビルド):
#[cfg(not(target_os = "ios"))]がシェルプラグインを iOS バイナリから除外するため、仮に権限がすり抜けても呼び出す対象が存在しない。
shell をどちらか一方のレイヤーだけに残すのは footgun である:プラグインの裏付けがない権限、あるいは権限によるゲートのないプラグインができてしまう。両レイヤーを一致させておくことで、どちらのチェックを忘れていても iOS 上のシェルコマンドは同じように失敗する。
generate_handler! 内での #[cfg]
同じ #[cfg(...)] 属性は tauri::generate_handler! マクロの 内部 でも機能し、コマンドをプラットフォームごとに個別に除外できる。これは非自明だが正当である:マクロは各エントリに対して属性を展開するため、除外されたコマンドは動作し得ないターゲットでは決して登録されない。
.invoke_handler(tauri::generate_handler![
commands::files::messages_list,
commands::settings::settings_get,
// ...other cross-platform commands...
// Build-pipeline commands spawn subprocesses, so they are not
// compiled on iOS — the attribute drops them from the handler list.
#[cfg(not(target_os = "ios"))]
commands::builder::generator_build_and_install,
#[cfg(not(target_os = "ios"))]
commands::builder::generator_cancel_build,
#[cfg(not(target_os = "ios"))]
commands::builder::generator_check_toolchain,
])iOS ではこれらのコマンドはハンドラーにまったく存在しないため、フロントエンドから呼び出すと、そのプラットフォームに存在すべきでないシェルベースのコードが実行されるのではなく、「command not found」エラーで失敗する。
トラブルシューティング
「IPC call failed」または「Permission denied」
コマンドが
generate_handler!に記載されているか確認するcore:defaultが権限リストに含まれているか確認するウィンドウラベルが Capability ファイルの
windows配列と一致しているか確認する
「Plugin not found」または「Feature not available」
main.rsで.plugin()によりプラグインが登録されているか確認するプラグインの権限が
capabilities/に含まれているか確認するdefault. json フロントエンド API 用にプラグインの npm パッケージがインストールされているか確認する
開発サーバーが Tauri コマンドを呼び出せない
remote.urls配列に開発サーバーの URL パターンが含まれているか確認するパターン
"http:は localhost の任意のポートをカバーする/ / localhost: */ **"
重要なポイント
core:defaultは必須 -- これがなければ IPC コマンドは一切動作しない各プラグインには独自の権限が必要 --
dialog:default、shell:defaultなどリモート URL は明示的な許可リストが必要 -- 開発サーバーの IPC アクセスに必要
ウィンドウラベルが一致する必要がある -- Capability の
windows配列にウィンドウラベルが含まれていなければならないコンパイル時チェックは存在しない -- 権限の欠落はサイレントに失敗するかランタイムで失敗する
本番環境では厳格な CSP を使用する -- 開発環境以外では
"csp": nullを避ける