Политика безопасности
Herkos работает с закрытыми ключами и зашифрованными сообщениями, поэтому мы серьёзно относимся к сообщениям о проблемах безопасности и предпочитаем узнать о проблеме раньше, а не позже.
Как сообщить об уязвимости
Пожалуйста, не открывайте публичный issue по проблемам безопасности.
Сообщите о ней конфиденциально по электронной почте security@herkos.email.
Что полезно указать: в чём проблема, как её воспроизвести, на какой платформе и версии вы проверяли и чего может добиться атакующий. Демонстрация уязвимости (proof of concept) очень помогает.
Никогда не указывайте в сообщении свой nsec, закрытый ключ или секрет bunker.
Мы стараемся подтверждать получение сообщений в течение нескольких дней. Поскольку Herkos — небольшой проект, пожалуйста, дайте разумное время на исправление, прежде чем раскрывать информацию публично. Мы с радостью укажем вас в бюллетене, если вы не против.
Что входит в область
Само приложение Herkos: обработка и хранение ключей, шифрование и
расшифровка сообщений (включая проверки отправителя NIP-59 и изоляцию Bcc
в local_packages/nostr_mail), блокировка приложения, связь с реле и мостами,
обработка вложений, а также процесс сборки и выпуска. Для Herkos Drive — также
его пакет протокола (packages/herkos_drive_protocol) и страница, которая
открывает его ссылки (herkos.app/f/); см. его собственный раздел ниже.
Что не входит в область
- Сам протокол Nostr и его NIP — о них сообщайте разработчикам протокола.
- Реле, мосты и серверы Blossom, которыми управляют третьи лица. Herkos поставляется со значениями по умолчанию, но не обслуживает их; сообщайте о проблемах их операторам.
- Исходный проект Nostr Mail Client, если проблема не связана именно с изменениями, внесёнными в Herkos.
- Отсутствие защит, которые мы уже описали как известное ограничение (см. ниже).
Известные ограничения, прямым текстом
Это компромиссы проектирования, а не уязвимости. Мы лучше запишем их, чем кто-то обнаружит их на собственном горьком опыте:
- Почта на обычные адреса не защищена сквозным шифрованием. Сообщения между пользователями Nostr используют NIP-17 gift wrap и зашифрованы сквозным шифрованием. Когда вы пишете на обычный адрес электронной почты, мост преобразует сообщение и может его прочитать.
- Блокировка приложения (PIN и биометрия) — это барьер удобства, а не шифрование хранимых данных. Она останавливает того, кто взял разблокированное устройство; она не защищает от атакующего с полным доступом к устройству или его хранилищу.
- В Windows нельзя потребовать вход только по биометрии. Windows Hello не позволяет выбрать способ, поэтому системный PIN-код всегда остаётся доступен как запасной вариант.
- Потеря ключа означает потерю аккаунта. Восстановления нет, и так задумано.
- Метаданные скрыты не полностью. Реле могут наблюдать закономерности подключений, и каждое реле видит ваш IP-адрес, даже если не может прочитать содержимое сообщений. Чего Herkos не выдаёт (с 30.09.2026), так это кто кому пишет, когда реле запрашивает аутентификацию NIP-42:
- Поиск, куда доставлять. Списки реле и серверов Blossom получателя
запрашиваются через отдельное соединение, которое никогда вас не идентифицирует, сначала на
реле, не требующих аутентификации (
purplepag.es,user.kindpag.es,nos.lol,offchain.pub). - Профили и планировщик. Имя и изображение, показываемые для любого другого человека (kind 0), и список реле DVM планировщика, когда вы планируете или отменяете письмо, запрашиваются так же: сначала анонимно, а если реле настаивает, — с временным ключом, описанным ниже, но никогда с вашим (с 01.10.2026; раньше реле, запросившее аутентификацию, получало ваш ключ и могло понять, чей профиль вы смотрите). Только ваш собственный профиль по-прежнему читается от вашего имени.
- Доставка. Gift wrap отправляются на DM-реле получателя через то же отдельное соединение. Если одно из них требует аутентификации, Herkos отвечает ключом, созданным специально для этого и хранящимся только в памяти, но никогда вашим; у каждого аккаунта на устройстве он свой. Реле всё же может видеть, что одно и то же устройство (тот же IP, тот же временный ключ) отправило несколько конвертов за сеанс.
- Большие письма. Зашифрованная копия письма размером более 32 КБ загружается на серверы Blossom, включая серверы получателей. Только ваши собственные серверы (ваш список Blossom) получают загрузку, авторизованную вашим ключом. Любой другой сервер получает её анонимно, а если настаивает на авторизации, — подписанную тем же временным ключом, что и выше (с 01.10.2026; раньше каждый сервер получал ваш ключ). Сервер, принимающий только известные ключи, её отклоняет, и копия остаётся на других серверах.
- Ваши собственные данные. Синхронизация почтового ящика, меток, настроек и черновиков проходит аутентификацию, если реле её запрашивает, от имени аккаунта, которому принадлежат данные, даже во время переключения аккаунтов. Вашим собственным реле это не сообщает ничего, чего они не знали: запросы и так называют ваш ключ. Ваши собственные списки реле и Blossom публичны и запрашиваются без вашей идентификации, как и реле, указанные в ссылке на письмо.
- Состояние «прочитано» и папки — публичные метаданные (пока). Когда вы отмечаете письмо прочитанным, помеченным звёздочкой, архивированным или перемещённым, публикуется незашифрованное событие метки NIP-32, привязанное к вашему открытому ключу, включая названия собственных папок. Отправитель, который знает идентификатор отправленного вам письма, может узнать, когда вы с ним что-то сделали. Шифрование этих меток запланировано; до тех пор считайте названия папок публичными.
- Push-уведомления и отложенная отправка используют сторонние сервисы.
Push-сервер, если вы его выберете (по умолчанию никакого;
api.nmail.liсrelay.nmail.liпо запросу), узнаёт ваш открытый ключ, push-токен и время получения почты; DVM планировщика узнаёт ваш открытый ключ и уже зашифрованные сообщения, которые он должен опубликовать. Оба включаются только по желанию и описаны вPRIVACY.md. Текст push-уведомления выбирает push-сервер, и Herkos доверяет ему, только когда UnifiedPush доставляет его в зашифрованном виде (RFC 8291); незашифрованное содержимое лишь будит приложение, чтобы оно само забрало почту. - Веб-версия хранит ваш ключ в браузере, а это самое слабое для него место. Установленные приложения передают ваш закрытый ключ в защищённое хранилище операционной системы (Android Keystore, DPAPI в Windows, libsecret, связка ключей iOS/macOS). В браузере ничего этого нет: ключ лежит в хранилище сайта и проходит через JavaScript при каждой подписи, в пределах досягаемости любого кода, выполняемого на странице, — расширения браузера с доступом ко всем сайтам, уязвимости XSS в приложении или в зависимости, подменённой сборки, — и любого инфостилера, копирующего профиль браузера. Кроме того, нет момента, когда вы проверяете код один раз: подписанный исполняемый файл проверяется при установке, а веб-страница отдаёт новый код при каждом посещении. Входите в веб-версию через удалённое приложение для подписи (bunker NIP-46, Amber), чтобы ключ никогда не попадал в браузер, или используйте в ней одноразовый аккаунт и храните настоящий ключ в установленном приложении.
- Почта через мост заслуживает доверия лишь настолько, насколько заслуживает его мост. Herkos проверяет, что
сообщение, помеченное как пришедшее через мост, действительно подписано мостом, который вы
настроили (или одним из мостов по умолчанию). Он не может ничего проверить относительно
обычного адреса
From:, который передаёт мост. - Вложения открывает операционная система. Herkos никогда не запускает исполняемые файлы и скрипты и спрашивает, прежде чем передать любое другое вложение без предпросмотра системному приложению по умолчанию, но приложение, которое открывает файл, нам неподконтрольно.
Herkos Local Relay: что оно защищает и чего нет
Herkos Local Relay хранит на вашем устройстве события ваших приложений, в том числе частные (черновики, частные списки, получаемые вами конверты). Вот что их защищает и где проходит граница — для каждой платформы. О проблемах безопасности реле сообщайте так же, как о любых других (см. выше).
Вся база данных зашифрована, включая её журнал транзакций (SQLite3 Multiple Ciphers, AEGIS-256). Ключ — это 32 случайных байта, созданных на устройстве и хранящихся в защищённом хранилище системы: Keystore в Android, DPAPI в Windows, связка ключей (libsecret) в Linux. Вашего пароля у него нет, потому что реле должно запускаться само. Без ключа реле не запускается и сообщает об этом: оно никогда не открывает и не создаёт незашифрованную базу и никогда не удаляет ту, которую не может открыть.
| Если… | Android | Windows | Linux |
|---|---|---|---|
| кто-то копирует файл базы (резервная копия, синхронизируемая папка, образ диска) | Защищено | Защищено | Защищено |
| украли выключенное устройство или диск | Защищено: ключ в Keystore | Защищено, если не знают пароль вашей учётной записи Windows: DPAPI защищает им ключ | Защищено, если не знают пароль вашей связки ключей (почти всегда это пароль вашего сеанса) |
| другая учётная запись пользователя на том же устройстве | Защищено | Защищено: DPAPI работает отдельно для каждого пользователя | Защищено: у каждого пользователя своя связка ключей |
| другое приложение или программа, работающие от имени вашего пользователя | Защищено: Android изолирует каждое приложение, а Keystore отдаёт ключ только реле | Нет: DPAPI шифрует для пользователя, а не для приложения; программа, работающая от вашего имени, может запросить ключ так же, как реле | Нет: связка ключей вашего сеанса не отделяет приложения друг от друга |
| телефон с root-доступом или инструмент, выполняющий код от имени приложения | Нет | — | — |
| кто-то держит в руках разблокированное устройство | Только PIN или отпечаток пальца реле, если вы их задали | Так же | Так же |
| кто-то читает память реле во время его работы | Нет | Нет | Нет |
На компьютере граница DPAPI и связки ключей такая же, как у любой программы: они защищают от других пользователей и от того, кто унесёт диск, но не от вредоносной программы, уже работающей от вашего имени. Если вас беспокоит этот случай, защищает шифрование системного диска (BitLocker, LUKS) и отказ от запуска программ, которым вы не доверяете. В Linux без связки ключей (без Secret Service) реле не запускается и объясняет почему: оно никогда не хранит ключ в открытом виде.
Кто входит — на самом устройстве. Реле слушает только 127.0.0.1, а до
этого адреса может достучаться любое приложение на устройстве или
веб-страница в браузере. Поэтому:
- Приложение должно пройти сопряжение: оно появляется на экране реле, и вы его одобряете (с PIN или отпечатком пальца, если вы их задали). Любое приложение может назваться как угодно: одобряйте, только если вы только что запросили это из этого приложения.
- Веб-страница всегда проходит сопряжение, и сопряжение действует только оттуда, где оно было сделано: сопряжение приложения на устройстве ничего не открывает веб-странице, даже если она подписывает тем же ключом.
- Сопряжённое приложение читает и записывает только те виды событий, которые вы ему разрешили, и удаляет только те, которые может записывать. Отзыв сразу же его отключает.
- Несопряжённое приложение читает только ваши публичные события (которые и так публичны) и ничего не записывает, если только вы не включите настройку, которая впускает несопряжённые приложения устройства.
- Частные события выдаются только тому, кто докажет по NIP-42, что владеет ключом, которому они принадлежат, а конверт — только его получателю.
Чего оно здесь не защищает:
- Вредоносное приложение на устройстве может замедлить реле или заставить его расходовать память. Прочитать что-либо частное таким образом оно не может.
- Пока реле спит или не работает, его порт свободен. В Android оно засыпает после 10 минут без подключений; на компьютере порт свободен, пока вы его не запустили. Другое приложение могло бы слушать этот порт и выдавать себя за реле. Приложения Herkos будут проверять ключ реле, прежде чем отправлять ему что-либо частное; пока они этого не делают, и до тех пор это реальная граница.
- На компьютере другие пользователи этого компьютера могут подключиться как несопряжённое приложение: читать ваши публичные события и запрашивать сопряжение.
Локальная сеть, если вы её включите (по умолчанию она выключена):
- Только
wss://, с собственным сертификатом реле; никогда незашифрованныйws://за пределами устройства. - Ничего до аутентификации (NIP-42) ключом из вашего списка. Соединение, которое не сделает этого за 30 секунд, закрывается, а у локальной сети собственный лимит подключений: она никогда не занимает подключения приложений устройства.
- Ключ из списка читает ваши публичные события и свои собственные частные и записывает только события, подписанные им самим. Удаление его из списка его отключает.
- Сертификат действителен только для домашних имён (
localhost,.local, частные адреса): даже если кто-то украдёт его ключ, он не поможет подписать интернет-домен на устройствах, которые его установили.
Чего оно здесь не защищает: любой в той же сети видит, что у устройства открыт порт и сколько трафика через него проходит, хотя и не что именно; а если у устройства публичный адрес (без роутера посередине), этот порт виден из интернета, хотя он по-прежнему требует ключ из вашего списка.
Копии. Зашифрованная копия защищена паролем (scrypt и XChaCha20-Poly1305): без него её никто не откроет, в том числе и мы. Экспорт в JSONL не шифруется и содержит ваши частные события в открытом виде; приложение об этом предупреждает.
Блокировка (PIN, а также отпечаток пальца или Windows Hello) запрашивается при открытии приложения, после 30 секунд вне его и для одобрения сопряжения. Это барьер удобства, как в Mail: она ничего не шифрует. В Android при заданном PIN нельзя делать снимки экрана и нет миниатюры среди недавних приложений, а начиная с Android 12 окно никакого другого приложения не может оказаться поверх окна реле, пока вы им пользуетесь.
Herkos Drive: что оно защищает и чего нет
Herkos Drive хранит ваши файлы на серверах Blossom, а список ваших файлов и
папок — на реле Nostr, и то и другое в зашифрованном на вашем устройстве виде.
Вот что их защищает и где проходят границы. Все подробности — в
spec-drive.md и в модели угроз amenazas-drive.md, в
packages/herkos_drive_protocol/; что видит каждое реле и каждый сервер — в
политике конфиденциальности. Сообщайте о
проблемах безопасности Drive так же, как о любых других (см. выше).
Чего реле и серверы сделать не могут:
- Прочитать ваши файлы или их имена. Каждый блок файла шифруется AES-256-GCM ключом его собственной ревизии; имена, папки, размеры, даты и ключи передаются запечатанными XChaCha20-Poly1305 ключом папки, в которой они находятся. Ничто не выводится из содержимого: один и тот же файл, загруженный дважды, даёт разные блоки.
- Незаметно изменить, подменить или переместить что-либо. Каждый блок проверяется по манифесту, запечатанному в записи его файла, а каждая запись подписана ключом тома и запечатана для своего места (том, идентификатор и папка): реле не может выдать одну запись за другую или один блок за другой.
- Вернуть старую версию. Приложение никогда не принимает запись старше той, что у него уже есть для того же идентификатора.
- Писать от вашего имени, имея только ключ тома. То, что пишут ваши устройства, несёт метку владельца — HMAC с ключом, который не даёт ни одна ссылка; запись или удаление без неё не принимаются, и приложение вас предупреждает.
Чего оно не защищает:
- Картину вашего Drive. Реле могут подсчитать ваши файлы и папки, увидеть форму дерева и то, когда меняется каждая запись; серверы видят примерно, какого размера каждый файл (блоки дополняются до 64 КиБ, записи — до степени двойки). Каждое реле и каждый сервер видят ваш IP-адрес. Используйте Tor или Orbot на уровне системы, если это для вас важно.
- То, что кто-то уже скачал. Удаление ссылки или человека сразу даёт новые ключи тому, что он мог открыть, так что он не откроет то, что вы добавите позже; вернуть то, что он уже сохранил, это не может.
- Утёкшую ссылку. Ссылка без пароля и есть ключ. Браузер может сохранить её в истории до того, как страница уберёт её из адресной строки. Для всего, что требует осторожности, задайте ссылке пароль и передайте его другим путём или поделитесь с аккаунтом человека. Слабый пароль со временем можно подобрать: тот, у кого есть ссылка, может перебирать офлайн.
- Страницу
herkos.app/f/, которая работает в браузере того, кто открывает ссылку. Она отдаётся со строгой Content-Security-Policy, Subresource Integrity и без стороннего кода, но тот, кто контролирует веб-хостинг, мог бы отдать другую страницу. Это предел любой веб-страницы, которая расшифровывает в браузере. - Того, у кого был ключ тома (ваш или переданный со ссылкой на папку): он всё ещё может удалить блоки, загруженные с этим ключом, пока они не будут загружены заново. Ключ тома можно сменить (Настройки → Ключ тома): ваши другие устройства переходят на новый сами.
- Ваше устройство. Список файлов кешируется в зашифрованном виде, а его ключ хранится в защищённом хранилище системы; файл, который вы скачиваете или открываете, записывается в открытом виде туда, куда вы выберете. PIN Drive — барьер удобства, как в Mail.
- Квантовый компьютер в будущем. Блоки и печати симметричны (AES-256, XChaCha20), но ваш локатор зашифрован NIP-44 на secp256k1: тот, кто сохранит его сегодня и взломает secp256k1 завтра, сможет открыть весь Drive.
Как это проверяется. Две внутренние проверки по модели угроз (2 ноября 2026 года) и исправления по их итогам; тесты того, что показывает каждое событие и каждый блок; фаззинг каждого обработчика того, что приходит извне (события, печати, манифесты, ссылки, резервные копии). Внешнего аудита пока нет: он запланирован до публичной беты, и его отчёт будет опубликован полностью. Drive ещё находится в разработке.
Поддерживаемые версии
Исправления безопасности применяются к последней выпущенной версии. Учитывая размер проекта, старые версии не поддерживаются — пожалуйста, обновитесь, прежде чем сообщать о проблеме.