本文へスキップ

セキュリティ

セキュリティ問題の報告

Electron の脆弱性の適切な開示方法については、SECURITY.mdを参照してください。

上流の Chromium の脆弱性について:Electron は、交互にリリースされる Chromium と常に最新の状態を保っています。詳細については、Electron リリース タイムラインドキュメントを参照してください。

はじめに

Web 開発者は通常、ブラウザの強力なセキュリティネットを享受しています。私たちが記述するコードに関連するリスクは比較的少ないです。私たちのウェブサイトにはサンドボックス内で限られた権限が付与され、私たちは、大規模なエンジニアチームによって構築されたブラウザをユーザーが利用し、新しく発見されたセキュリティ脅威に迅速に対応できると信頼しています。

Electron を使用する場合、Electron はWebブラウザではないことを理解することが重要です。Electron を使用すると、使い慣れたWebテクノロジーで機能豊富なデスクトップアプリケーションを構築できますが、あなたのコードははるかに大きな権限を持ちます。JavaScript は、ファイルシステム、ユーザーシェルなどにアクセスできます。これにより、高品質のネイティブアプリケーションを構築できますが、固有のセキュリティリスクは、コードに付与される追加の権限とともに増加します。

これを踏まえ、信頼できないソースから任意のコンテンツを表示すると、Electron では処理できない重大なセキュリティリスクが生じることに注意してください。実際、最も人気のある Electron アプリ(Atom、Slack、Visual Studio Codeなど)は、主にローカルコンテンツ(またはNode統合のない信頼できる安全なリモートコンテンツ)を表示します。アプリケーションがオンラインソースからコードを実行する場合は、コードが悪意のあるものでないことを確認する責任があります。

一般的なガイドライン

セキュリティは皆の責任です

Electron アプリケーションのセキュリティは、フレームワークの基礎(_Chromium_、_Node.js_)、Electron 自体、すべての NPM 依存関係、そしてあなたのコードの全体的なセキュリティの結果であることを覚えておくことが重要です。そのため、いくつかの重要なベストプラクティスに従うことがあなたの責任です。

  • **アプリケーションを最新の Electron フレームワークリリースに更新してください。**製品をリリースする際には、Electron、Chromium 共有ライブラリ、Node.jsで構成されるバンドルも提供しています。これらのコンポーネントに影響を与える脆弱性は、アプリケーションのセキュリティに影響を与える可能性があります。Electron を最新バージョンに更新することで、_nodeIntegration のバイパス_などの重大な脆弱性が既に修正されており、アプリケーションで悪用されることがなくなります。詳細については、「Electron の最新バージョンを使用する」を参照してください。

  • **依存関係を評価してください。**NPM は数十万もの再利用可能なパッケージを提供していますが、信頼できるサードパーティライブラリを選択する責任はあなたにあります。既知の脆弱性の影響を受ける古いライブラリを使用したり、保守状態の悪いコードに依存したりすると、アプリケーションのセキュリティが危険にさらされる可能性があります。

  • **安全なコーディングプラクティスを採用してください。**アプリケーションの最初の防御線は、あなた自身のコードです。クロスサイトスクリプティング(XSS)などの一般的なWebの脆弱性は、Electronアプリケーションへのセキュリティへの影響が大きいため、安全なソフトウェア開発のベストプラクティスを採用し、セキュリティテストを実行することを強くお勧めします。

信頼できないコンテンツの分離

信頼できないソース(例:リモートサーバー)からコードを受信してローカルで実行する場合は常に、セキュリティ上の問題が存在します。例として、デフォルトの BrowserWindow 内にリモートWebサイトが表示されていることを考えてください。攻撃者が何らかの方法でそのコンテンツを変更した場合(ソースを直接攻撃するか、アプリと実際の宛先の間に位置するか)、ユーザーのマシンでネイティブコードを実行できるようになります。

警告

いかなる状況下でも、Node.js統合を有効にしてリモートコードをロードして実行しないでください。代わりに、Node.jsコードを実行するには、ローカルファイル(アプリケーションと一緒にパッケージ化されたファイル)のみを使用してください。リモートコンテンツを表示するには、<webview>タグまたはWebContentsViewを使用し、nodeIntegrationを無効にしてcontextIsolationを有効にするようにしてください。

Electron セキュリティ警告

セキュリティ警告と推奨事項は、開発者コンソールに出力されます。バイナリの名前が Electron の場合にのみ表示され、開発者が現在コンソールを確認していることを示します。

process.envまたはwindowオブジェクトのいずれかにELECTRON_ENABLE_SECURITY_WARNINGSまたはELECTRON_DISABLE_SECURITY_WARNINGSを設定することで、これらの警告を強制的に有効または無効にできます。

チェックリスト:セキュリティに関する推奨事項

少なくとも次の手順に従って、アプリケーションのセキュリティを向上させる必要があります。

  1. 安全なコンテンツのみをロードする
  2. リモートコンテンツを表示するすべてのレンダラーでNode.js統合を無効にする
  3. すべてのレンダラーでコンテキスト分離を有効にする
  4. プロセスのサンドボックス化を有効にする
  5. リモートコンテンツをロードするすべてのセッションでses.setPermissionRequestHandler()を使用する
  6. webSecurityを無効にしない
  7. Content-Security-Policyを定義する restricive なルールを使用する(例:script-src 'self'
  8. allowRunningInsecureContentを有効にしない
  9. 実験的な機能を有効にしない
  10. enableBlinkFeaturesを使用しない
  11. <webview>allowpopupsを使用しない
  12. <webview>:オプションとパラメーターを確認する
  13. ナビゲーションを無効にするか制限する
  14. 新しいウィンドウの作成を無効にするか制限する
  15. 信頼できないコンテンツでshell.openExternalを使用しない
  16. Electron の最新バージョンを使用する
  17. すべての IPC メッセージのsenderを検証する
  18. file://プロトコルの使用を避け、カスタムプロトコルの使用を優先する
  19. 変更できるヒューズを確認する

設定ミスと安全でないパターンを自動的に検出するには、Electronegativityを使用できます。Electron を使用してアプリケーションを開発する際の潜在的な弱点と実装のバグの詳細については、この開発者および監査者向けのガイドを参照してください。

1. 安全なコンテンツのみをロードする

アプリケーションに含まれていないリソースは、HTTPSなどの安全なプロトコルを使用してロードする必要があります。言い換えれば、HTTPなどの安全でないプロトコルを使用しないでください。同様に、WSよりもWSSFTPよりもFTPSなどを使用することをお勧めします。

理由

HTTPSには2つの主な利点があります。

  1. データの整合性を確保し、アプリケーションとホスト間の転送中にデータが変更されていないことを主張します。
  2. ユーザーと宛先ホスト間のトラフィックを暗号化し、アプリとホスト間で送信される情報の盗聴を困難にします。

方法

main.js(メインプロセス)
// Bad
browserWindow.loadURL('http://example.com')

// Good
browserWindow.loadURL('https://example.com')
index.html(レンダラープロセス)
<!-- Bad -->
<script crossorigin src="http://example.com/react.js"></script>
<link rel="stylesheet" href="http://example.com/style.css">

<!-- Good -->
<script crossorigin src="https://example.com/react.js"></script>
<link rel="stylesheet" href="https://example.com/style.css">

2. リモートコンテンツに対してNode.js統合を有効にしない

情報

この推奨事項は、Electron 5.0.0以降のデフォルト動作です。

リモートコンテンツを読み込むレンダラー(BrowserWindowWebContentsView、または<webview>)でNode.js統合を有効にしないことが非常に重要です。目的は、リモートコンテンツに付与する権限を制限することであり、攻撃者がウェブサイトでJavaScriptを実行できるようになった場合でも、ユーザーに被害を与えることを大幅に困難にすることです。

その後、特定のホストに対して追加の権限を付与できます。たとえば、https://example.com/をポイントするBrowserWindowを開く場合、そのウェブサイトに必要な機能のみを正確に付与し、それ以上は付与しません。

理由

クロスサイトスクリプティング(XSS)攻撃は、攻撃者がレンダラープロセスから飛び出してユーザーのコンピューターでコードを実行できる場合、より危険になります。クロスサイトスクリプティング攻撃は非常に一般的であり、問題ではありますが、その影響は通常、実行されたウェブサイトの操作に限定されます。Node.js統合を無効にすると、XSSが「リモートコード実行」(RCE)攻撃にエスカレートするのを防ぐのに役立ちます。

方法

main.js(メインプロセス)
// Bad
const mainWindow = new BrowserWindow({
webPreferences: {
contextIsolation: false,
nodeIntegration: true,
nodeIntegrationInWorker: true
}
})

mainWindow.loadURL('https://example.com')
main.js(メインプロセス)
// Good
const mainWindow = new BrowserWindow({
webPreferences: {
preload: path.join(app.getAppPath(), 'preload.js')
}
})

mainWindow.loadURL('https://example.com')
index.html(レンダラープロセス)
<!-- Bad -->
<webview nodeIntegration src="page.html"></webview>

<!-- Good -->
<webview src="page.html"></webview>

Node.js統合を無効にしても、Node.jsモジュールや機能を使用するAPIをウェブサイトに公開できます。プリロードスクリプトは引き続きrequireやその他のNode.js機能にアクセスできるため、開発者はcontextBridge APIを介して、リモートで読み込まれたコンテンツにカスタムAPIを公開できます。

3. コンテキスト分離を有効にする

情報

この推奨事項は、Electron 12.0.0以降のデフォルト動作です。

コンテキスト分離は、開発者がプリロードスクリプトとElectron APIのコードを専用のJavaScriptコンテキストで実行できるようにするElectronの機能です。実際には、Array.prototype.pushJSON.parseなどのグローバルオブジェクトは、レンダラープロセスで実行されているスクリプトによって変更できません。

Electronは、Chromiumのコンテンツスクリプトと同じ技術を使用して、この動作を有効にします。

nodeIntegration: falseを使用する場合でも、強力な分離を強制し、Nodeプリミティブの使用を防ぐには、contextIsolation必ず使用する必要があります。

情報

contextIsolationの詳細と有効化の方法については、専用のコンテキスト分離ドキュメントを参照してください。

4. プロセスサンドボックスを有効にする

サンドボックス化は、オペレーティングシステムを使用して、レンダラープロセスがアクセスできるものを大幅に制限するChromiumの機能です。すべてのレンダラーでサンドボックスを有効にする必要があります。メインプロセスを含む、サンドボックス化されていないプロセスで信頼できないコンテンツの読み込み、読み取り、または処理は推奨されません。

情報

プロセスサンドボックスの詳細と有効化の方法については、専用のプロセスサンドボックスドキュメントを参照してください。

5. リモートコンテンツからのセッション権限要求を処理する

Chromeを使用中に権限要求が表示されたことがあるかもしれません。これは、ウェブサイトがユーザーが手動で承認する必要がある機能(通知など)を使用しようとするたびに表示されます。

このAPIはChromium権限APIに基づいており、同じタイプの権限を実装しています。

理由

デフォルトでは、開発者がカスタムハンドラーを手動で構成しない限り、Electronはすべての権限要求を自動的に承認します。堅牢なデフォルトですが、セキュリティを重視する開発者は、正反対のことを前提とする場合があります。

方法

main.js(メインプロセス)
const { session } = require('electron')
const { URL } = require('url')

session
.fromPartition('some-partition')
.setPermissionRequestHandler((webContents, permission, callback) => {
const parsedUrl = new URL(webContents.getURL())

if (permission === 'notifications') {
// Approves the permissions request
callback(true)
}

// Verify URL
if (parsedUrl.protocol !== 'https:' || parsedUrl.host !== 'example.com') {
// Denies the permissions request
return callback(false)
}
})

6. webSecurityを無効にしない

情報

この推奨事項はElectronのデフォルトです。

レンダラープロセス(BrowserWindowWebContentsView、または<webview>)でwebSecurityプロパティを無効にすると、重要なセキュリティ機能が無効になることは、すでに推測されているかもしれません。

本番アプリケーションではwebSecurityを無効にしないでください。

理由

webSecurityを無効にすると、同一生成元ポリシーが無効になり、allowRunningInsecureContentプロパティがtrueに設定されます。つまり、異なるドメインから安全でないコードの実行が許可されます。

方法

main.js(メインプロセス)
// Bad
const mainWindow = new BrowserWindow({
webPreferences: {
webSecurity: false
}
})
main.js(メインプロセス)
// Good
const mainWindow = new BrowserWindow()
index.html(レンダラープロセス)
<!-- Bad -->
<webview disablewebsecurity src="page.html"></webview>

<!-- Good -->
<webview src="page.html"></webview>

7. コンテンツセキュリティポリシーを定義する

コンテンツセキュリティポリシー(CSP)は、クロスサイトスクリプティング攻撃やデータ挿入攻撃に対する追加の保護レイヤーです。Electron内で読み込むウェブサイトでは、CSPを有効にすることをお勧めします。

理由

CSPを使用すると、コンテンツを提供するサーバーは、Electronがその特定のウェブページに対して読み込むことができるリソースを制限および制御できます。https://example.comは、定義したオリジンからのスクリプトの読み込みを許可する必要がありますが、https://evil.attacker.comからのスクリプトは実行を許可するべきではありません。CSPを定義することで、アプリケーションのセキュリティを簡単に向上させることができます。

方法

次のCSPでは、Electronは現在のウェブサイトとapis.example.comからのスクリプトを実行できます。

// Bad
Content-Security-Policy: '*'

// Good
Content-Security-Policy: script-src 'self' https://apis.example.com

CSP HTTPヘッダー

ElectronはContent-Security-Policy HTTPヘッダーを尊重します。これは、ElectronのwebRequest.onHeadersReceivedハンドラーを使用して設定できます。

main.js(メインプロセス)
const { session } = require('electron')

session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
callback({
responseHeaders: {
...details.responseHeaders,
'Content-Security-Policy': ['default-src \'none\'']
}
})
})

CSPメタタグ

CSPの推奨される配信メカニズムはHTTPヘッダーです。ただし、file://プロトコルを使用してリソースを読み込む場合は、この方法を使用できません。場合によっては、<meta>タグを使用してマークアップに直接ポリシーを設定することが役立つ場合があります。

index.html(レンダラープロセス)
<meta http-equiv="Content-Security-Policy" content="default-src 'none'">

8. allowRunningInsecureContentを有効にしない

情報

この推奨事項はElectronのデフォルトです。

デフォルトでは、ElectronはHTTPS経由で読み込まれたウェブサイトが安全でないソース(HTTP)からスクリプト、CSS、またはプラグインを読み込んで実行することを許可しません。allowRunningInsecureContentプロパティをtrueに設定すると、その保護が無効になります。

ウェブサイトの最初のHTMLをHTTPS経由で読み込み、その後にHTTP経由でリソースを読み込もうとすることは、「混合コンテンツ」としても知られています。

理由

HTTPS経由でコンテンツを読み込むと、読み込まれたリソースの信頼性と整合性が保証され、トラフィック自体が暗号化されます。詳細については、安全なコンテンツのみを表示するセクションを参照してください。

方法

main.js(メインプロセス)
// Bad
const mainWindow = new BrowserWindow({
webPreferences: {
allowRunningInsecureContent: true
}
})
main.js(メインプロセス)
// Good
const mainWindow = new BrowserWindow({})

9. 実験的な機能を有効にしない

情報

この推奨事項はElectronのデフォルトです。

Electronの高度なユーザーは、experimentalFeaturesプロパティを使用して、実験的なChromium機能を有効にすることができます。

理由

実験的な機能は、その名前が示唆するように、実験的なものであり、すべてのChromiumユーザーに対して有効化されていません。さらに、Electron全体への影響は、おそらくテストされていません。

正当な使用例は存在しますが、自分のやっていることがわからない限り、このプロパティを有効にしないでください。

方法

main.js(メインプロセス)
// Bad
const mainWindow = new BrowserWindow({
webPreferences: {
experimentalFeatures: true
}
})
main.js(メインプロセス)
// Good
const mainWindow = new BrowserWindow({})

10. enableBlinkFeaturesを使用しない

情報

この推奨事項はElectronのデフォルトです。

Blinkは、Chromiumのレンダリングエンジンの名前です。experimentalFeaturesと同様に、enableBlinkFeaturesプロパティを使用すると、デフォルトで無効になっている機能を有効にすることができます。

理由

一般的に言って、機能がデフォルトで有効になっていないのには、おそらく正当な理由があります。特定の機能を有効にするための正当な使用例は存在します。開発者として、機能を有効にする必要がある理由、その結果、アプリケーションのセキュリティへの影響を正確に理解する必要があります。いかなる状況下でも、推測的に機能を有効にしないでください。

方法

main.js(メインプロセス)
// Bad
const mainWindow = new BrowserWindow({
webPreferences: {
enableBlinkFeatures: 'ExecCommandInJavaScript'
}
})
main.js(メインプロセス)
// Good
const mainWindow = new BrowserWindow()

11. WebView で allowpopups を使用しない

情報

この推奨事項はElectronのデフォルトです。

<webview> を使用している場合、<webview> タグに読み込まれたページやスクリプトで新しいウィンドウを開く必要があるかもしれません。allowpopups 属性は、window.open() メソッドを使用して新しいBrowserWindows を作成することを可能にします。それ以外の場合は、<webview> タグは新しいウィンドウを作成することは許可されません。

理由

ポップアップが必要ない場合は、デフォルトで新しいBrowserWindows の作成を許可しない方が良いでしょう。これは、最小限必要なアクセス権限の原則に従ったものです。ウェブサイトが必要とする機能であることが分かるまで、新しいポップアップの作成を許可しないでください。

方法

index.html(レンダラープロセス)
<!-- Bad -->
<webview allowpopups src="page.html"></webview>

<!-- Good -->
<webview src="page.html"></webview>

12. 作成前に WebView オプションを確認する

Node.js 統合が有効になっていないレンダラプロセスで作成された WebView は、それ自体で統合を有効にすることができません。ただし、WebView は常に独自の webPreferences を持つ独立したレンダラプロセスを作成します。

メインプロセスから新しい<webview> タグの作成を制御し、その webPreferences がセキュリティ機能を無効にしていないことを確認することをお勧めします。

理由

<webview> は DOM 内に存在するため、Node.js 統合が無効になっている場合でも、ウェブサイトで実行されているスクリプトによって作成される可能性があります。

Electron は、レンダラプロセスを制御するさまざまなセキュリティ機能を開発者が無効にすることを可能にしています。ほとんどの場合、開発者はこれらの機能を無効にする必要はありません。そのため、新しく作成された<webview> タグに対して異なる設定を許可するべきではありません。

方法

<webview> タグがアタッチされる前に、Electron はホスト webContentswill-attach-webview イベントを発生させます。このイベントを使用して、可能性のある安全でないオプションを持つ webViews の作成を防ぎます。

main.js(メインプロセス)
app.on('web-contents-created', (event, contents) => {
contents.on('will-attach-webview', (event, webPreferences, params) => {
// Strip away preload scripts if unused or verify their location is legitimate
delete webPreferences.preload

// Disable Node.js integration
webPreferences.nodeIntegration = false

// Verify URL being loaded
if (!params.src.startsWith('https://example.com/')) {
event.preventDefault()
}
})
})

繰り返しますが、このリストはリスクを最小限に抑えるだけであり、排除するものではありません。ウェブサイトを表示することが目的であれば、ブラウザの方が安全な選択肢です。

13. ナビゲーションを無効化または制限する

アプリケーションにナビゲーションの必要がない場合、または既知のページにのみナビゲーションする必要がある場合、ナビゲーションをその既知の範囲に完全に制限し、その他の種類のナビゲーションを許可しないことをお勧めします。

理由

ナビゲーションは一般的な攻撃ベクトルです。攻撃者がアプリケーションに現在のページから離れてナビゲーションさせることができれば、インターネット上のウェブサイトを開かせる可能性があります。webContents がより安全になるように構成されている場合でも(nodeIntegration が無効になっているか、contextIsolation が有効になっているなど)、ランダムなウェブサイトを開かせることは、アプリケーションの悪用を容易にします。

一般的な攻撃パターンは、攻撃者がアプリケーションのユーザーを、アプリケーションが攻撃者のページのいずれかに移動するように操作することです。これは通常、リンク、プラグイン、またはその他のユーザー生成コンテンツを介して行われます。

方法

アプリケーションにナビゲーションの必要がない場合は、will-navigate ハンドラで event.preventDefault() を呼び出すことができます。アプリケーションが移動する可能性のあるページがわかっている場合は、イベントハンドラで URL を確認し、期待する URL と一致する場合にのみナビゲーションを許可します。

URL には Node のパーサーを使用することをお勧めします。単純な文字列比較ではだまされることがあります。startsWith('https://example.com') テストでは、https://example.com.attacker.com が通過してしまいます。

main.js(メインプロセス)
const { URL } = require('url')
const { app } = require('electron')

app.on('web-contents-created', (event, contents) => {
contents.on('will-navigate', (event, navigationUrl) => {
const parsedUrl = new URL(navigationUrl)

if (parsedUrl.origin !== 'https://example.com') {
event.preventDefault()
}
})
})

14. 新しいウィンドウの作成を無効化または制限する

既知のウィンドウセットがある場合は、アプリケーションで追加のウィンドウの作成を制限することをお勧めします。

理由

ナビゲーションと同様に、新しい webContents の作成は一般的な攻撃ベクトルです。攻撃者は、アプリケーションに新しいウィンドウ、フレーム、または他のレンダラプロセスを作成させようとします。それらは、以前よりも多くの権限を持つ、または以前は開けなかったページが開かれたものになります。

必要になることがわかっているウィンドウ以外にウィンドウを作成する必要がない場合は、作成を無効にすることで、無料でセキュリティを少し向上させることができます。これは、1 つの BrowserWindow を開き、実行時に任意の数の追加ウィンドウを開く必要がないアプリケーションの場合によく見られます。

方法

webContents は、新しいウィンドウを作成する前に、そのウィンドウオープンハンドラ に委任します。ハンドラは、他のパラメータの中でも、ウィンドウの開く要求された url と、その作成に使用されたオプションを受け取ります。ウィンドウの作成を監視し、予期しないウィンドウの作成を拒否するハンドラを登録することをお勧めします。

main.js(メインプロセス)
const { app, shell } = require('electron')

app.on('web-contents-created', (event, contents) => {
contents.setWindowOpenHandler(({ url }) => {
// In this example, we'll ask the operating system
// to open this event's url in the default browser.
//
// See the following item for considerations regarding what
// URLs should be allowed through to shell.openExternal.
if (isSafeForExternalOpen(url)) {
setImmediate(() => {
shell.openExternal(url)
})
}

return { action: 'deny' }
})
})

15. 信頼できないコンテンツで shell.openExternal を使用しない

シェルモジュールのopenExternal API を使用すると、デスクトップのネイティブユーティリティで指定されたプロトコル URI を開くことができます。たとえば、macOS では、この関数は open ターミナルコマンドユーティリティに似ており、URI とファイルタイプの関連付けに基づいて特定のアプリケーションを開きます。

理由

openExternal の不適切な使用は、ユーザーのホストを侵害するために利用される可能性があります。openExternal が信頼できないコンテンツで使用されると、任意のコマンドを実行するために利用される可能性があります。

方法

main.js(メインプロセス)
//  Bad
const { shell } = require('electron')
shell.openExternal(USER_CONTROLLED_DATA_HERE)
main.js(メインプロセス)
//  Good
const { shell } = require('electron')
shell.openExternal('https://example.com/index.html')

16. 最新バージョンの Electron を使用する

常に最新の Electron バージョンを使用するように努める必要があります。新しいメジャーバージョンがリリースされた場合は、できるだけ早くアプリケーションを更新することを試みる必要があります。

理由

古いバージョンの Electron、Chromium、および Node.js を使用して構築されたアプリケーションは、より新しいバージョンのこれらのコンポーネントを使用しているアプリケーションよりも攻撃されやすくなります。一般的に、古いバージョンの Chromium と Node.js のセキュリティ上の問題と脆弱性は、より広く利用可能です。

Chromium と Node.js はどちらも、何千人もの才能ある開発者によって構築された素晴らしいエンジニアリングの成果です。その人気を考えると、そのセキュリティは同様に熟練したセキュリティ研究者によって注意深くテストおよび分析されています。これらの研究者の多くは責任ある開示を行い、これは一般的に、研究者が公開する前に Chromium と Node.js に問題を修正するための時間を与えることを意味します。潜在的なセキュリティ上の問題があまり知られていない、最新の Electron バージョン(そして Chromium と Node.js)を実行している場合、アプリケーションはより安全になります。

方法

Electron のBreaking Changes ドキュメントを参照して、更新が必要なコードがないか確認しながら、メジャーバージョンごとにアプリケーションを移行します。

17. すべての IPC メッセージの sender を検証する

信頼できないレンダラに対してアクションを実行したり、情報を送信したりしないように、受信した IPC メッセージの sender プロパティを常に検証する必要があります。

理由

理論的には、すべての Web フレームはメインプロセスに IPC メッセージを送信できます。これには、場合によっては iframe や子ウィンドウも含まれます。event.reply を介してユーザーデータを送信者に戻したり、レンダラがネイティブに実行できない特権アクションを実行したりする IPC メッセージがある場合は、サードパーティの Web フレームをリッスンしていないことを確認する必要があります。

デフォルトで、**すべての** IPC メッセージの sender を検証する必要があります。

方法

main.js(メインプロセス)
// Bad
ipcMain.handle('get-secrets', () => {
return getSecrets()
})

// Good
ipcMain.handle('get-secrets', (e) => {
if (!validateSender(e.senderFrame)) return null
return getSecrets()
})

function validateSender (frame) {
// Value the host of the URL using an actual URL parser and an allowlist
if ((new URL(frame.url)).host === 'electronjs.org') return true
return false
}

18. file:// プロトコルの使用を避け、カスタムプロトコルを使用する

ローカルページは、file:// プロトコルではなく、カスタムプロトコルから提供する必要があります。

理由

file:// プロトコルは、Electron では Web ブラウザよりも多くの権限を取得し、ブラウザでも http/https URL とは異なる方法で扱われます。カスタムプロトコルを使用すると、読み込み可能なものとそのタイミングについてさらに多くの制御を維持しながら、従来の Web URL の動作にさらに近づけることができます。

file:// で実行されているページは、マシン上のすべてのファイルに一方的にアクセスできるため、XSS 問題を使用してユーザーのマシンから任意のファイルをロードできます。カスタムプロトコルを使用すると、プロトコルを特定のファイルセットの提供のみに制限できるため、このような問題を防ぐことができます。

方法

protocol.handle の例に従って、カスタムプロトコルからファイル/コンテンツを提供する方法を学習してください。

19. 変更可能なヒューズを確認する

Electronには、便利なオプションが多数含まれていますが、多くのアプリケーションでは必要のないものも含まれています。独自のElectronバージョンをビルドする必要を避けるために、これらのオプションはヒューズを使用してオンオフを切り替えることができます。

理由

runAsNodenodeCliInspectなどのヒューズは、特定の環境変数またはCLI引数を使用してコマンドラインから実行された場合、アプリケーションの動作を変化させます。これらは、アプリケーションを通じてデバイス上でコマンドを実行するために使用できます。

これにより、外部スクリプトは、本来許可されていない可能性のあるコマンドを、アプリケーションが権限を持っている場合に実行できるようになります。

方法

これらのヒューズの切り替えを容易にするために、@electron/fusesというモジュールを作成しました。使用方法と潜在的なエラーケースの詳細については、そのモジュールのREADMEを確認し、ドキュメントのヒューズの切り替え方法を参照してください。