Безопасность
For information on how to properly disclose an Electron vulnerability, see SECURITY.md.
Что касается уязвимостей в Chromium, обнаруженных ранее: Electron постоянно обновляет информацию о новых версиях Chromium. Дополнительную информацию можно найти в документе «Сроки выпуска Electron».
Предисловие
Как веб-разработчики, мы обычно используем надёжную систему безопасности браузера, а риски, связанные с кодом, что мы пишем, относительно мелкие. Наши веб-сайты имеют ограниченные полномочия в песочнице, и мы верим, что пользователи довольны браузером, созданным большой командой инженеров, которая может быстро реагировать на последние обнаруженные угрозы безопасности.
Когда вы работаете в среде Электрон, важно понимать, что это не веб браузер. Электрон позволяет создавать функционально развитые приложения для настольных компьютеров с помощью веб технологий, но ваш код обладает большими возможностями. JavaScript имеет доступ к файловой системе, пользовательским скриптам и т. д. Благодаря этим возможностям вы можете создавать высококачественные нативные приложения, но это так же множит риски увеличивающиеся с дополнительными полномочиями вашего кода.
Учтите что показ произвольного содержимого от недоверенных источников влечет за собой риски безопасности, которые Электрон не предназначен купировать. Так как фактически, самые популярные приложения Electron (Atom, Slack, Visual Studio Code, и т.д.) отображают в основном локальное содержимое (или доверенное, защищённое удаленное содержимое без интеграции Node), если ваше приложение выполняет код из онлайн-источника, вы обязаны убедиться, что этот код не является вредоносным.
Общие рекомендации
Безопасность — это ответственность каждого
Важно помнить, что безопасность вашего Electron приложения является результатом общей безопасности основы платформы (Chromium, Node.js), самого Electron, всех NPM-зависимостей и вашего кода. Поэтому вы обязаны следовать нескольким важным рекомендациям:
-
Поддерживайте приложение в актуальном состоянии с помощью последней версии фреймворка Electron. Выпуская свой продукт, вы также поставляете пакет, состоящий из Electron, общей библиотеки Chromium и Node.js. Уязвимости, затрагивающие эти компоненты могут повлиять на безопасность вашего приложения. При обновлении Election до последней версии, будьте уверены, что критические уязвимости (такие, как обход интеграции node) уже исправлены и не могут быть использованы в вашем приложении. Дополнительную информацию смотрите в разделе "Используйте актуальную версию Electron".
-
Оцените свои зависимости. В то время как NPM предоставляет полмиллиона многоразовых пакетов, вы несете ответственность за выбор надежных библиотек третьей стороны. Если вы используете устаревшие библиотеки, в которых есть известные уязвимости, или полагаетесь на плохо поддерживаемый код, безопасность вашего приложения может оказаться под угрозой.
-
Используйте безопасные методы программирования Первая линия защиты вашей заявки — ваш собственный код. Распространенные веб-уязвимости, такие как межсайтовый скриптинг (XSS), оказывают более серьезное влияние на безопасность приложений Electron, поэтому настоятельно рекомендуется следовать передовым методам разработки безопасного программного обеспечения и проводить тестирование на безопасность.
Изоляция для ненадежного контента
Проблемы безопасности возникают всякий раз, когда вы получаете код из ненадежного источника (напр., удаленный сервер) и выполняете его локально. В качестве примера рассмотрим удаленный веб-сайт, отображаемый в стандартном BrowserWindow. Если злоумышленнику каким-то образом удастся изменить указанный контент (либо напрямую атаковав источник, либо оказавшись между вашим приложением и конечным пунктом назначения), он сможет выполнить собственный код на компьютере пользователя.
Ни при каких обстоятельствах не загружайте и не выполняйте удаленный код с включенной интеграцией Node.js. Вместо этого используйте только локальные файлы (упакованные вместе с вашим приложением) для выполнения кода Node.js. Для отображения удаленного контента используйте тег <webview> или WebContentsView. Не забудьте отключить nodeIntegration и включить contextIsolation.
Предупреждения и рекомендации по безопасности отображаются в консоли разработчика. Они появляются только в том случае, если имя бинарного файла это Electron, что указывает на то, что разработчик в данный момент просматривает консоль.
Вы можете принудительно включить или выключить эти предупреждения в настройках ELECTRON_ENABLE_SECURITY_WARNINGS или ELECTRON_DISABLE_SECURITY_WARNINGS на любом process.env или объекте window.
Список: Рекомендации по безопасности
Чтобы повысить безопасность своего приложения, вам следует выполнить как минимум следующие действия:
- Загружайте только безопасный контент
- Не включайте интеграцию Node.js для удаленного контента
- Enable context isolation in all renderers
- Включить песочницу процесса
- Используйте
ses.setPermissionRequestHandler()в сессиях с загрузкой удаленного контента - Не выключайте
webSecurity - Определите
Content-Security-Policyи используйте ограничительные правила (i.e.script-src 'self') - Не включайте
allowRunningInsecureContent - Не включайте экспериментальные функции
- Не испольхуйте
enableBlinkFeatures <webview>: Не используйтеallowpopups<webview>: Проверить настройки и параметры- Отключить или ограничить навигацию
- Отключить или ограничить создание новых окон
- Не используйте
shell.openExternalс ненадежным контентом - Использовать текущую версию Electron
- Validate the
senderof all IPC messages - Избегайте использования протокола
file://и предпочитайте использование пользовательских протоколов - Check which fuses you can change
- Не предоставляйте доступ к API Electron ненадежному веб контенту
1. Загружайте только безопасный контент
Все ресурсы не включенные в ваше приложение должны быть загружены с использованием безопасного протокола HTTPS. Откажитесь от не безопасных протоколов, таких как HTTP. Так же мы рекомендуем WSS over WS, FTPS over FTP, и т. п.
Почему?
HTTPS имеет два основных преимущества:
- Он обеспечивает целостность данных, подтверждая, что данные не были изменены при передаче между вашим приложением и хостом.
- Он шифрует трафик между вашим пользователем и целевым хостом, что затрудняет прослушивание информации, передаваемой между вашим приложением и хостом.
Как?
// Плохо
browserWindow.loadURL('http://example.com')
// Хорошо
browserWindow.loadURL('https://example.com')
<!-- Плохо -->
<script crossorigin src="http://example.com/react.js"></script>
<link rel="stylesheet" href="http://example.com/style.css">
<!-- Хорошо -->
<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.
Крайне важно не включать интеграцию Node. js ни в одном из средств визуализации (BrowserWindow, WebContentsView или <webview>), которые загружают удаленный контент. The goal is to limit the powers you grant to remote content, thus making it dramatically more difficult for an attacker to harm your users should they gain the ability to execute JavaScript on your website.
After this, you can grant additional permissions for specific hosts. For example, if you are opening a BrowserWindow pointed at https://example.com/, you can give that website exactly the abilities it needs, but no more.
Почему?
A cross-site-scripting (XSS) attack is more dangerous if an attacker can jump out of the renderer process and execute code on the user's computer. Cross-site-scripting attacks are fairly common - and while an issue, their power is usually limited to messing with the website that they are executed on. Disabling Node.js integration helps prevent an XSS from being escalated into a so-called "Remote Code Execution" (RCE) attack.
Как?
// Bad
const mainWindow = new BrowserWindow({
webPreferences: {
contextIsolation: false,
nodeIntegration: true,
nodeIntegrationInWorker: true
}
})
mainWindow.loadURL('https://example.com')
// Good
const mainWindow = new BrowserWindow({
webPreferences: {
preload: path.join(app.getAppPath(), 'preload.js')
}
})
mainWindow.loadURL('https://example.com')
<!-- Bad -->
<webview nodeIntegration src="page.html"></webview>
<!-- Good -->
<webview src="page.html"></webview>
При отключении интеграции с Node.js, можно по-прежнему использовать API на вашем сайте, которые используют модули или функции Node.js. Preload scripts continue to have access to require and other Node.js features, allowing developers to expose a custom API to remotely loaded content via the contextBridge API.
3. Включить изоляцию контекста
Context Isolation is the default behavior in Electron since 12.0.0.
Context isolation is an Electron feature that allows developers to run code in preload scripts and in Electron APIs in a dedicated JavaScript context. In practice, that means that global objects like Array.prototype.push or JSON.parse cannot be modified by scripts running in the renderer process.
Electron uses the same technology as Chromium's Content Scripts to enable this behavior.
Even when nodeIntegration: false is used, to truly enforce strong isolation and prevent the use of Node primitives contextIsolation must also be used.
Beware that disabling context isolation for a renderer process by setting nodeIntegration: true also disables process sandboxing for that process. See section below.
For more information on what contextIsolation is and how to enable it please see our dedicated Context Isolation document.
4. Включить песочницу процесса
This recommendation is the default behavior in Electron since 20.0.0.
Additionally, process sandboxing can be enforced for all renderer processes application wide: Enabling the sandbox globally
Disabling context isolation (see above) also disables process sandboxing, regardless of the default, sandbox: false or globally enabled sandboxing!
Sandboxing is a Chromium feature that uses the operating system to significantly limit what renderer processes have access to. You should enable the sandbox in all renderers. Loading, reading or processing any untrusted content in an unsandboxed process, including the main process, is not advised.
For more information on what Process Sandboxing is and how to enable it please see our dedicated Process Sandboxing document.
5. Handle session permission requests from remote content
You may have seen permission requests while using Chrome: they pop up whenever the website attempts to use a feature that the user has to manually approve ( like notifications).
The API is based on the Chromium permissions API and implements the same types of permissions.
Почему?
By default, Electron will automatically approve all permission requests unless the developer has manually configured a custom handler. While a solid default, security-conscious developers might want to assume the very opposite.
Как?
const { session } = require('electron')
const { URL } = require('node:url')
session
.defaultSession
.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)
}
})
Note: session.defaultSession is only available after app.whenReady is called.
6. Не выключайте webSecurity
This recommendation is Electron's default.
You may have already guessed that disabling the webSecurity property on a renderer process (BrowserWindow, WebContentsView, or <webview>) disables crucial security features.
Do not disable webSecurity in production applications.
Почему?
Disabling webSecurity will disable the same-origin policy and set allowRunningInsecureContent property to true. In other words, it allows the execution of insecure code from different domains.
Как?
// Bad
const mainWindow = new