Chrome拡張機能の権限設計とは?permissionsとhost_permissionsを最小限にする考え方

公開日: 

前回の記事「IndexedDBとは?Chrome拡張機能でコメント履歴を保存する方法」では、コメント履歴をブラウザ内へ保存する方法を紹介しました。

Chrome拡張機能で機能を増やしていくと、manifest.json に権限を追加する場面があります。

たとえば、設定を保存するための storage、現在開いているタブへ一時的に処理を行うための activeTab、特定サイトへアクセスするための host_permissions です。

権限は、追加すればするほど便利になるものではありません。

不要な権限まで含めると、利用者に不安を与えます。Chrome Web Storeへ公開する場合は、なぜその権限が必要なのかを説明できる状態にしておく必要があります。

この記事では、初心者向けに permissionshost_permissionscontent_scripts.matches、optional permissions、activeTab の違いを整理します。

最後に、公開前に manifest.json を見直すチェックリストもまとめます。

Chrome拡張機能で必要な権限だけを選ぶ最小権限設計の図解
Chrome拡張機能で必要な権限だけを選ぶ最小権限設計の図解

Chrome拡張機能の権限とは

Chrome拡張機能の権限は、拡張機能が利用できるAPIやアクセス先を表します。

通常は、manifest.json に必要な権限を書きます。

たとえば、chrome.storage APIを使う場合は、次のように storage 権限を追加します。

{
  "manifest_version": 3,
  "name": "Storage Sample",
  "version": "1.0.0",
  "permissions": ["storage"]
}

特定サイトに対する処理が必要な場合は、対象URLを指定します。

{
  "host_permissions": [
    "https://example.com/*"
  ]
}

権限によっては、インストール時や権限追加時に利用者へ警告が表示されます。

権限設計では、機能が動くことだけでなく、利用者が納得できる範囲に絞ることが重要です。

最小権限の原則

権限設計の基本は、必要な権限だけを要求することです。

Chrome Web StoreのUse of Permissionsポリシーでは、実装済みの機能やサービスに必要な最も狭い権限を要求するよう案内されています。

将来使うかもしれない権限を、先回りして追加することは避けます。

たとえば、https://example.com/* だけで動く拡張機能に、すべてのサイトを対象にする <all_urls> を追加する必要はありません。

{
  "host_permissions": [
    "https://example.com/*"
  ]
}

対象サイトを限定すると、次のメリットがあります。

  • 利用者へ機能の範囲を説明しやすい
  • 意図しないサイトへのアクセスを避けやすい
  • 不具合やセキュリティ問題の影響範囲を小さくしやすい
  • Chrome Web Storeの審査で権限の理由を説明しやすい

最小権限は、権限をゼロにするという意味ではありません。

必要な機能を実現できる範囲で、最も狭い権限を選ぶという考え方です。

権限を書く場所を整理する

Manifest V3では、目的に応じて権限を書く場所が分かれています。

主な項目は次の通りです。

項目役割
permissionsChrome APIを使うための権限storageactiveTabscripting
host_permissions指定したホストへアクセスするための権限https://example.com/*
content_scripts.matchescontent scriptを自動実行するページの範囲https://example.com/*
optional_permissions必要になった時点で要求するAPI権限tabs
optional_host_permissions必要になった時点で要求するホスト権限https://*.example.com/*

似ている項目もありますが、役割は同じではありません。

manifest.jsonで権限を宣言する主な項目の比較図
manifest.jsonで権限を宣言する主な項目の比較図

permissionsはChrome APIの利用権限

permissions には、Chrome APIを使うために必要な権限を書きます。

たとえば、前々回の記事で使った chrome.storage APIには、storage 権限が必要です。

{
  "permissions": [
    "storage"
  ]
}

ページへJavaScriptを動的に挿入する場合は、scripting 権限が候補になります。

{
  "permissions": [
    "activeTab",
    "scripting"
  ]
}

すべてのChrome APIが権限を必要とするわけではありません。

また、権限によって利用者へ表示される警告も異なります。

追加する前に、Chrome公式のPermissions一覧で、役割と警告の有無を確認します。

host_permissionsはアクセス先の範囲

host_permissions には、拡張機能がアクセスするホストをmatch patternで書きます。

たとえば、https://example.com/ 配下だけを対象にする場合は、次のように書きます。

{
  "host_permissions": [
    "https://example.com/*"
  ]
}

複数のサイトが必要なら、必要なサイトだけを追加します。

{
  "host_permissions": [
    "https://example.com/*",
    "https://api.example.net/*"
  ]
}

すべてのURLへアクセスできるようにする <all_urls> もあります。

{
  "host_permissions": [
    "<all_urls>"
  ]
}

ただし、対象サイトを限定できる機能で <all_urls> を使うと、範囲が広すぎます。

<all_urls> が必要な機能もありますが、何となく追加するものではありません。

次の順番で考えます。

  1. 対象サイトを1つに限定できないか
  2. 対象ドメインを限定できないか
  3. 利用者の操作時だけ一時的にアクセスできないか
  4. それでも全サイトへのアクセスが必要か

content_scripts.matchesは自動実行するページ

content scriptを自動実行する場合は、content_scripts.matches に対象ページを書きます。

{
  "content_scripts": [
    {
      "matches": [
        "https://example.com/*"
      ],
      "js": [
        "content.js"
      ]
    }
  ]
}

この設定では、https://example.com/ 配下のページで content.js が読み込まれます。

content scriptを使う記事でも、対象ページを限定しました。

機能が特定サイト専用なら、matches も必要な範囲に絞ります。

{
  "matches": [
    "https://example.com/dashboard/*"
  ]
}

対象URLを狭くすると、関係のないページで処理が動くことを避けられます。

host_permissionsとcontent_scripts.matchesの違い

host_permissionscontent_scripts.matches は、どちらもURLを指定します。

しかし、目的は異なります。

項目主な目的
host_permissions指定ホストに対する拡張機能のアクセスを許可する
content_scripts.matchescontent scriptを自動実行するページを指定する

たとえば、popupやbackground service workerから特定APIへリクエストする場合は、host_permissions を検討します。

{
  "host_permissions": [
    "https://api.example.com/*"
  ]
}

特定ページへボタンを追加するcontent scriptを自動実行する場合は、content_scripts.matches を設定します。

{
  "content_scripts": [
    {
      "matches": [
        "https://example.com/orders/*"
      ],
      "js": [
        "content.js"
      ]
    }
  ]
}

必要に応じて両方を使う場合もあります。

ただし、同じURLが書かれているから同じ役割だと考えず、機能ごとに必要性を確認します。

activeTabで一時的なアクセスにする

activeTab は、利用者が拡張機能を呼び出したときに、現在のタブへ一時的にアクセスするための権限です。

たとえば、利用者が拡張機能アイコンを押したときだけ、現在のページへ処理を実行する場合に向いています。

{
  "permissions": [
    "activeTab",
    "scripting"
  ],
  "action": {}
}

background service workerでは、次のようにスクリプトを挿入できます。

chrome.action.onClicked.addListener(async (tab) => {
  if (!tab.id) {
    return;
  }

  await chrome.scripting.executeScript({
    target: { tabId: tab.id },
    files: ["content.js"]
  });
});

activeTab は、利用者の操作をきっかけに一時的なアクセスを与えます。

常にすべてのサイトへアクセスする必要がない機能なら、広いhost permissionの代わりに使えるか検討します。

ただし、自動実行が必要なcontent scriptには向きません。

利用者が操作する前からページ内で処理を動かす必要がある場合は、対象サイトを限定した content_scripts.matches などを検討します。

tabs権限を安易に追加しない

タブを操作する処理を書くと、tabs 権限が必要だと思うかもしれません。

しかし、chrome.tabs APIのすべての機能で tabs 権限が必要になるわけではありません。

Chrome公式資料では、tabs 権限はTabオブジェクトの一部の機密性が高いプロパティへアクセスするために使うと説明されています。

現在のタブに対する一時的なアクセスで足りる場合は、activeTab を検討します。

まず、使いたいAPIの公式資料で必要な権限を確認します。

そのうえで、tabs が本当に必要な場合だけ追加します。

optional permissionsを使う

インストール時には不要で、特定機能を使うときだけ必要になる権限があります。

その場合は、optional permissionsを検討します。

{
  "optional_permissions": [
    "tabs"
  ],
  "optional_host_permissions": [
    "https://*.example.com/*"
  ]
}

optional permissionsは、実行時に chrome.permissions APIで要求します。

const granted = await chrome.permissions.request({
  permissions: ["tabs"]
});

if (!granted) {
  console.log("権限が許可されませんでした");
  return;
}

console.log("権限が許可されました");

利用者が機能を使おうとした時点で権限を要求すると、なぜ必要なのかを説明しやすくなります。

拒否された場合も考慮します。

権限がないと使えない機能だけを無効にし、拡張機能全体が壊れないように設計します。

optional permissionsでも説明は必要

optional permissionsにすれば、どの権限でも自由に追加してよいわけではありません。

利用者から見ると、権限を許可する判断が必要なことは同じです。

権限を要求する前に、画面上で次の内容を説明できるようにします。

  • どの機能で使うのか
  • 何へアクセスするのか
  • 許可しない場合は何が使えないのか
  • 他の機能は使えるのか

機能と権限の関係が分かると、利用者は判断しやすくなります。

警告が表示される権限を確認する

権限によっては、インストール時に警告が表示されます。

また、公開済み拡張機能の更新で新しい警告が必要になる権限を追加すると、利用者の確認が必要になります。

Chrome公式資料では、更新で新しい警告が発生する場合、利用者が新しい権限を受け入れるまで拡張機能が無効化されると案内されています。

権限追加は、コードを1行追加するだけの変更ではありません。

利用者体験、公開時の説明、アップデート手順にも影響します。

公開前だけでなく、機能追加時にも権限を見直します。

権限設計の具体例

設定を保存するpopup

popupでON/OFF設定を保存するだけなら、storage 権限を使います。

{
  "permissions": [
    "storage"
  ],
  "action": {
    "default_popup": "popup.html"
  }
}

Webページへアクセスしないなら、host_permissions は不要です。

特定サイトへボタンを追加する

https://example.com/ 配下だけへボタンを追加するなら、content_scripts.matches を限定します。

{
  "content_scripts": [
    {
      "matches": [
        "https://example.com/*"
      ],
      "js": [
        "content.js"
      ]
    }
  ]
}

関係のないサイトまで対象にしません。

利用者が押したときだけ現在ページを処理する

拡張機能アイコンを押したときだけ現在ページを処理するなら、activeTabscripting を検討します。

{
  "permissions": [
    "activeTab",
    "scripting"
  ],
  "action": {}
}

すべてのサイトへ常時アクセスする必要があるかを見直せます。

特定APIへリクエストする

popupやbackground service workerから特定APIへリクエストする場合は、そのホストだけを指定します。

{
  "host_permissions": [
    "https://api.example.com/*"
  ]
}

外部APIへデータを送信する場合は、権限だけでなく、送信内容、利用目的、保存先も説明します。

公開前に権限表を作る

Chrome Web Storeへ公開する前に、権限と機能の対応表を作ります。

たとえば、次のように整理します。

権限またはアクセス先使用する機能必要な理由さらに狭くできるか
storagepopup設定保存ON/OFF設定を端末内へ保存する設定保存に必要
activeTab現在ページの処理利用者が操作したタブだけ処理する常時host permissionより狭い
scriptingスクリプト挿入利用者操作後に content.js を実行する動的挿入に必要
https://example.com/*特定サイト用機能対象ページだけでcontent scriptを動かすパス単位で限定できるか確認

この表があると、不要な権限を見つけやすくなります。

Chrome Web Storeの権限説明を書くときにも使えます。

Chrome拡張機能の機能を整理し権限を最小化して説明する流れの図解
Chrome拡張機能の機能を整理し権限を最小化して説明する流れの図解

公開前チェックリスト

公開前に、manifest.json を見ながら次の項目を確認します。

  • 実装済み機能で使っていない権限が残っていないか
  • 将来使うかもしれない権限を先回りして追加していないか
  • host_permissions を対象ドメインやパスへ限定できないか
  • <all_urls> が本当に必要か
  • content scriptの matches が広すぎないか
  • 常時アクセスではなく activeTab で実現できないか
  • インストール時ではなくoptional permissionsで要求できないか
  • tabs 権限が本当に必要か
  • 外部APIへの送信先と送信内容を説明できるか
  • 権限を拒否された場合の動作を決めているか
  • 権限追加を伴うアップデートの影響を確認したか
  • Chrome公式のPermissions一覧で警告の有無を確認したか

権限だけでなくデータの扱いも確認する

権限を最小限にしても、データの扱いが不明確なら利用者は安心できません。

たとえば、Webページから取得した情報を保存する場合は、次の内容を整理します。

  • 何を取得するか
  • どこへ保存するか
  • 外部サーバーへ送信するか
  • 第三者へ提供するか
  • 利用者が削除できるか
  • 保持期間をどうするか

ローカル保存だけなら、そのことを明記します。

外部送信があるなら、送信先と目的を説明します。

権限設計とプライバシー説明は、別々の作業ではありません。

次の記事では、Chrome拡張機能のプライバシーポリシーに何を書くかを整理します。

参考リンク

まとめ

この記事では、Chrome拡張機能の権限設計を整理しました。

権限は、機能を動かすために必要な範囲だけを要求します。

permissions にはChrome APIの権限、host_permissions にはアクセス先、content_scripts.matches にはcontent scriptを自動実行するページを書きます。

利用者が操作した現在タブだけでよい場合は、activeTab を検討します。

特定機能を使うときだけ必要な権限は、optional permissionsを検討します。

<all_urls>tabs を一律に避けるのではなく、本当に必要か、より狭い権限で実現できないかを確認します。

公開前には、権限と機能の対応表を作ります。

利用者へ必要性を説明できない権限があれば、削除するか、設計を見直します。




Your Message

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

スポンサードリンク

記事が気に入ったらシェアお願いします

PAGE TOP ↑