Безопасность в qub
Дата вступления в силу: 23 сентября 2026 Версия: 1.1 — обзор точности реализации
Для исследователей — быстрая справка:
- Куда отправлять отчеты: support@qub.social с префиксом субъекта
[SECURITY].- Что включить: уязвимость, шаги для воспроизведения и любые доказательства концепции.
- Наш ответ: мы подтверждаем получение в течение 3 рабочих дней и стремимся отправить исправление в течение 90 дней.
- Безопасная гавань: мы не будем предпринимать юридические действия против добросовестных исследований, которые следуют правилам в §12 (нет доступа к данным, которые не принадлежат вам, отсутствие деградации сервиса, не хранить полученные данные дольше, чем необходимо для демонстрации проблемы, предоставить нам разумный срок для раскрытия).
Полные сведения содержатся в §12 (Координированное раскрытие).
Кто мы такие
qub.social управляется VSPRY AUSTRALIA PTY LIMITED (ABN 41 631 026 330), Level 38, 71 Eagle Street, Brisbane QLD 4000, Australia. Упоминания «qub», «мы», «нас» и «наш» означают данное юридическое лицо.
Контакт по безопасности: support@qub.social с префиксом темы [SECURITY].
1. Наш подход
qub — это инфраструктура доверия. Продукт не имеет ценности, если он небезопасен, поэтому безопасность — это не функция, а субстрат. Эта страница описывает в конкретных терминах, как мы защищаем наш стек, Ваши данные и целостность запечатанного контента.
Ценность проверяемого временного обязательства растет по мере того, как все больше интернета становится сгенерированным машинами. Проверенная транзакция хранения или якорь журнала прозрачности могут установить, что шифротекст существовал не позднее своего времени блока; запечатанный артефакт отдельно подтверждает целостность содержимого, привязку к раунду drand и любые подписи авторства. Сохранение этих утверждений отдельно — это стандарт, которому соответствует эта страница.
Мы не просим Вас доверять нам. Мы проектируем так, чтобы требуемое от нас доверие было настолько малым, насколько это возможно, и там, где доверие требуется, мы точно объясняем, чему именно доверяют и почему.
Три принципа определяют каждое проектное решение:
- Минимизируйте то, что сервер может видеть. В стандартном потоке сообщений браузера открытый текст и ключ-обертка остаются на вашем устройстве. Серверное запечатывание Builder, совместная подпись пакта и явно включенное восстановление имеют разные границы доверия, которые приведены ниже. Когда мы храним метаданные, мы ограничиваем их тем, что необходимо выбранной функции.
- Сделать компромисс локально ограниченным. Нарушение любого из компонентов (наш сервер, почтовый провайдер, узел drand) не должно раскрывать защищённое содержимое, которое ещё не достигло времени своего раскрытия.
- Сделайте протокол подлежащим проверке. Запечатанный артефакт можно проверить от конца до конца с помощью публичной криптографии. Вам не нужно доверять qub сервис для проверки qub артефакт.
2. Модель угроз
2.1 От чего мы защищаем
- Злоумышленник, который получает доступ только для чтения к нашим хранимым на сервере данным до времени раскрытия. В стандартном режиме частного браузера они получают метаданные и непрозрачные упакованные байты, а не открытый текст или K. Эта защита не распространяется на K, явно сохранённый для восстановления, на публичную/неприкрытую доставку после его раунда в drand, или на открытый текст, временно предоставленный Сборщику.
/api/v1/sealи рабочие процессы пакта. - Злоумышленник, который перехватывает трафик между вашим браузером и нашей инфраструктурой. TLS завершается на нашем CDN-узле; закрытые данные уже зашифрованы до передачи.
- Злоумышленник, который вмешивается в хранимую полезную нагрузку. Аутентификация внешней оболочки (когда присутствует), каноническое декодирование, хеш тела,
qub_idповторное выведение, круговая привязка и необязательные подписи делают проверку подделки неудачной; просмотрщик отказывается отображать её. - Злоумышленник, который пытается привязать поддельный адрес электронной почты автора к ключу подписи. Для подтверждения по электронной почте требуется наличие как приватного ключа для подписи, так и одноразового кода, отправленного на почтовый ящик.
- Скомпрометированный оператор маяка drand. Сеть drand использует пороговые BLS-подписи через несколько независимых операторов; меньшинство не может подделать подписи раннего выпуска.
2.2 От чего мы не можем защитить
Мы честны в отношении наших пределов. qub не может защищать от:
- Компрометация вашего устройства до того, как вы его запрете. Локальные кейлоггеры, вредоносные расширения браузера или физический доступ к незаблокированному устройству могут захватывать открытый текст в момент его создания.
- Обрушение порога drand. Несколько независимых организаций управляют сетью drand специально, чтобы затруднить это, но это не криптографически невозможно: если достаточное количество операторов сговорятся, они смогут получить ключи тайм-локов раньше времени.
- Свойства выпуска действительной копии. Публичный/неупакованный qub становится расшифровываемым после его раунда drand. Приватный/упакованный qub дополнительно требует K; любой, кто получит как сохраненные байты, так и K, сможет расшифровать после раунда. Записи постоянного хранения и закрепленного журнала нельзя восстановить просто удалив их с поверхности продукта qub.
- Глобальный противник, который взламывает основную криптографию (AES-GCM, предположения о парировании BLS12-381, SHA3-256, ML-DSA-65). Если эти примитивы выйдут из строя, у криптографической экосистемы в целом будут более серьезные проблемы.
3. Криптография на стороне клиента
В стандартном потоке сообщений браузера шифрование содержимого происходит до запроса на загрузку. Существуют два явных пути, которые различаются: Builder /api/v1/seal намеренно отправляет открытый текст и ключ K, сгенерированный вызывающим, Работнику для защиты в памяти, а постановка/со-подпись пакта отправляет подписанный структурированный пакт в службу, чтобы она могла завершить двусторонний артефакт. Ни одно из исключений не следует ошибочно принимать за сквозное шифрование через браузерный путь.
3.1 Timelock-шифрование
qub использует tlock — основанное на идентичности шифрование, привязанное к будущему раунду маяка drand. Шифрование выполняется в Вашем браузере с использованием публичного ключа сети drand; ключ расшифровки публично выпускается сетью drand только тогда, когда достигается целевой раунд. Никто, включая нас, не может реконструировать ключ расшифровки заранее.
Мы нацеливаемся на цепочку quicknet:
- 3-секундный период раунда
- Несвязанный режим (каждый раунд независим)
- BLS12-381 G1 подписи
- Хеш цепочки
52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971
Публичный ключ и время genesis цепочки quicknet вкомпилированы в клиент. Мы не запрашиваем параметры цепочки во время выполнения, поэтому вредоносный узел не может подставить цепочку, которую мы контролируем.
3.2 Симметричное шифрование
Схема tlock оборачивает контентный ключ AES-256-GCM. AES-GCM обеспечивает аутентифицированное шифрование: один перевёрнутый бит в шифротексте приводит к сбою расшифровки, а не к молча испорченному открытому тексту.
3.3 Каноническая сериализация
Структуры протокола сериализуются с использованием детерминированного CBOR (RFC 8949 §4.2 основное детерминированное кодирование). Две реализации, кодирующие одну и ту же логическую структуру, производят идентичный CBOR. Полные запечатанные полезные нагрузки являются не детерминированный: tlock и шифрование внешней оболочки используют свежие случайные значения. Хеш тела вычисляется по необработанным байтам тела, в то время как каноническое кодирование делает окружающие подписанные/сетевые структуры однозначными.
Мы написали CBOR-кодировщик вручную как для нашей клиентской, так и для серверной реализации, не полагаясь на общую библиотеку сериализации — требование — точность, а не эргономика, и property-тесты выполняются в обеих реализациях, чтобы убедиться, что они согласуются.
Регрессионный тест утверждает, что канонический wire-формат не содержит ни одной байтовой последовательности бренда qub за пределами ключа поля протокольного примитива qub_id. Wire-формат намеренно бренд-нейтрален — любой соответствующий просмотровщик (наш или сторонний) может отрендерить любой qub из постоянного хранилища, независимо от того, какое развёртывание его запечатало. Тест — это растяжка, которая предотвращает то, чтобы будущее изменение случайно вбило ссылку на бренд в байты, которые, оказавшись в постоянном хранилище, уже не могут быть переписаны.
3.4 Хеширование тела и pre-reveal целостность
Каждая запечатанная полезная нагрузка содержит хеш SHA3-256 от своих необработанных байтов тела. Хеш связан с qub_id и, когда включена подпись авторства, в поле ввода подписи V2. Просмотрщик пересчитывает её после расшифровки и отклоняет несоответствие.
32-байтовый идентификатор содержимого qub_id получается из предобразца размером 108 байт, охватывающего версию протокола, тип содержания, временные метки создания и разблокировки, необязательную временную метку исхода (или её нулевой сигнал), целевой раунд drand, хеш тела и SHA3-256 необязательного нормализованного по NFC заголовка. Шлюз или CDN не могут изменить какое-либо связанное поле последовательно и при этом пройти повторное вычисление. Заголовки ограничены 100 NFC-кодовыми точками и отклоняются для общего класса враждебных/контрольных кодовых точек (включая переопределения bidi, символы с нулевой шириной, блок тегов, BOM, C0, C1 и DEL).
3.5 Подписание (ML-DSA-65)
Подписание авторства использует ML-DSA-65 (FIPS 204), стандартизованную NIST постквантовую схему подписи. Мы сознательно выбрали постквантовый примитив для подписания, потому что запечатанный контент постоянен: подпись, которая проверяется сегодня, должна продолжать проверяться через десятилетия, в том числе после того, как крупномасштабные квантовые компьютеры станут практичными.
Ключи для подписания генерируются в браузере. Локальный секрет оборачивается в невынимаемый ключ WebCrypto перед сохранением в IndexedDB. Если используется функция восстановления между устройствами в рамках учетной записи, зашифрованный AEAD портативный ключ сохраняется на стороне сервера; его шифротекст секретного ключа привязан к неизменяемому идентификатору учетной записи, и сервис проверяет публичный конверт, но не может расшифровать секретный материал. Сырые байты приватного ключа не отправляются на сервер. Публичные ключи и записи аттестации сохраняются для проверки и отображения идентичности.
То же in-browser tlock-расшифрование применяется внутри эмбеда qub: когда запечатанный qub рендерится через <qub-embed> на сторонней странице, расшифрование по-прежнему происходит в iframe эмбеда в браузере зрителя. Эмбед не меняет модель доверия — открытый текст никогда не расшифровывается на сервере qub.
3.6 Публичная атрибуция — Opt-In
Запечатанные qubs не несут on-chain-указателя на их создателя, если только создатель явно не выберет прикрепить его. Когда Вы запечатываете qub, эталонное приложение выпускает тег хранилища Author (64-символьный hex-«отпечаток» Вашего подписного публичного ключа) только тогда, когда «Публичная атрибуция» включена на шаге выбора даты. С выключенным переключателем — по умолчанию — никакой Author-тег не пишется, и qub не атрибутирован в постоянном хранилище: ничто в хранилище не связывает загрузку с Вашим handle, Вашим email или Вашими другими qubs. С включённым переключателем «отпечаток» разрешается в Ваш @handle через цепочку аттестаций в §6.3 / §10, и обратный отсчёт у зрителя показывает «Запечатано @{handle}» до раскрытия.
Это намеренная защита от риска перечисления, который создал бы постоянно включённый Author-тег: третья сторона, узнавшая «отпечаток» создателя, могла бы иначе обыскать постоянное хранилище по тегу и реконструировать всю историческую активность этого создателя. Opt-in-атрибуция закрывает этот канал — только те qubs, которые создатель явно выбирает атрибутировать, появляются под «отпечатком» в постоянном хранилище.
Страница профиля /u/{handle} — это карточка подтверждённой идентичности — handle, опциональное отображаемое имя + URL, значок «verified email» (без адреса) и короткая форма криптографического «отпечатка». Она не перечисляет qubs создателя. Посетители, которые хотят увидеть конкретный qub от создателя, переходят по URL доставки этого qub напрямую.
3.7 Внешняя обёртка шифрования
Даже после того, как расшифровка с таймлоком становится математически возможной — как только подпись drand для привязанного раунда будет опубликована — только канонический слой таймлока позволил бы индексеру массово расшифровывать обнаруживаемые квабы. Частная доставка закрывает этот канал с помощью дополнительного симметричного слоя вокруг байтов, зашифрованных таймлоком (Протокол §13). Публичная доставка намеренно опускает этот обертку, чтобы уведомления, встраивания и ссылки на обнаружение могли работать без секретного фрагмента.
Обёртка использует AES-256-GCM, стандартизованный NIST аутентифицированный шифр, со свежим 256-битным ключом K, генерируемым для каждого qub браузерным CSPRNG. K связан с qub_id qub как аутентифицированные дополнительные данные, поэтому ключ от одного qub нельзя переиспользовать для расшифрования другого qub.
K никогда не достигает наших серверов в стандартном режиме приватного браузера. Он закодирован в фрагменте URL общей ссылки (https://qub.social/c/<tx_id>#<base64url(K)>). Браузеры не передают фрагменты URL на серверы — RFC 3986 помещает фрагмент вне запроса — поэтому qub.social, шлюзы хранения, CDN и мониторинг запросов не видят K в этом потоке. Сохраненный OuterWrapper это распознаваемый структурированный CBOR, но его поле аутентифицированного шифротекста скрывает внутреннее SealedQub структура и не может быть открыта без K.
Чистые последствия:
- qub.social не может расшифровать стандартные защищённые печати приватного браузера, основываясь только на хранимых данных. Нарушение хранилища данных достигает непрозрачного шифротекста без ключа. Публичные qub и qub с включённым восстановлением имеют различную уязвимость по замыслу.
- Потеря фрагмента не может быть восстановлена без выбранного канала восстановления. Если вы сохраняете приватную ссылку без фрагмента и не включили восстановление, qub становится недоступным через эту ссылку. По этой причине в потоке запечатывания появляется явное уведомление «сохраните этот URL».
- Восстановление по желанию Когда вы соглашаетесь получать электронные письма о жизненном цикле создателя для кьюба И письмо совпадает с вашей проверенной личностью, мы принимаем K вместе с загрузкой, сохраняем полный URL доставки в зашифрованной истории вашей личности и используем его как ссылку в письме с подтверждением печати. Эта операция — серверный канал восстановления в обмен на некоторое сквозное целостное сохранение — активируется только при явном согласии и только для этого кьюба. По умолчанию используется крипто-удаление.
Серверный эндпоинт Worker /api/v1/seal (используемый ИИ-агентами и другими вызывающими API) требует, чтобы вызывающий сгенерировал K с помощью CSPRNG, сохранил его локально и передал в виде wrapper_key_b64url. Worker неизбежно видит в памяти и открытый текст, и K на этом явно доверенном пути, но не сохраняет ни того, ни другого. Обязательный Idempotency-Key не позволяет потерянному ответу создать второй тарифицируемый qub, а сохранённый вызывающим K можно объединить с воспроизведённым URL без фрагмента. Это отличается от пути браузера по умолчанию, где K никогда не достигает Worker, если только автор явно не включит восстановление.
4. Транспорт и edge
4.1 TLS
Трафик браузера к qub обслуживается через HTTPS на стороне Cloudflare. Ответы устанавливают строгую политику транспортного уровня HTTP (HTTP Strict Transport Security) (max-age=63072000; includeSubDomains; preload). Точная согласованная версия TLS и набор шифров управляются активной конфигурацией периферийного узла, а не задаются кодом приложения. Мы не предоставляем отдельно доступный исходный сервер.
4.2 Безопасность контента
Скомпилированный клиент обслуживается со строгими заголовками content-type и кеша. SPA-оболочка — единственный origin. Мы не встраиваем сторонние скрипты для аналитики или рекламы. Две сторонние точки касания в продукте обе узко ограничены: поток покупки полностью покидает SPA полностраничным редиректом на размещённый Stripe checkout (https://checkout.stripe.com/…) — UI Stripe никогда не выполняется в нашем origin, и мы никогда не видим данные карты — и поток запечатывания загружает виджет Cloudflare Turnstile, альтернативу CAPTCHA, сохраняющую приватность, который Cloudflare рендерит внутри собственного iframe-песочницы. Ни одна сторона не может прочитать остальную часть страницы.
Этот qub встроить iframe (обслуживается с qub.social/embed/{tx_id} и загружены на сайты третьих лиц embed.js) имеет свою собственную Политику безопасности контента. Его connect-src белый список это 'self', https://qub.social, https://arweave.net, https://ar-io.dev, https://permagate.io, https://api.drand.sh, и https://drand.cloudflare.com. Iframe работает с sandbox="allow-scripts allow-top-navigation-by-user-activation" (не allow-same-origin): главная страница не может читать свой DOM и не может перемещаться по хосту, кроме как после действия пользователя.
4.3 CORS и охват fetch
Браузерный клиент делает fetch-запросы только к:
- Наш собственный API (
api.qub.socialи эквиваленты стадии - Шлюзы хранения (только для чтения, для извлечения байтов в обёрнутом частном или чисто публичном виде — §3.6)
- конечные точки маяка drand (только для чтения, для подписей раунда времени раскрытия)
Назначения встроенного объекта определяются его CSP. Назначения основного SPA заданы в коде и конфигурации и проверяются браузером и средствами интеграции; целостность подресурсов не является механизмом контроля назначения в сети.
Встраиваемый элемент извлекает сохраненные байты через разрешенные источники qub/storage, распаковывает приватные полезные нагрузки в браузере с использованием K из фрагмента URL и получает подписи раундов времени раскрытия с двух разрешенных источников drand. Основное SPA использует набор резервных конечных точек из четырех элементов, установленный в config/drand-endpoints.json (drand.cloudflare.com, api.drand.sh, api2.drand.sh, и api3.drand.sh) поэтому сбой одной конечной точки не блокирует раскрытие. Встроенный CSP запрещает подключения вне его явного списка.
5. Серверная инфраструктура
5.1 Бессерверный edge
Наш API работает полностью на управляемой бессерверной среде выполнения на edge. Нет ни VM, ни контейнеров, ни постоянных серверных процессов, которыми мы администрируем. Это резко сокращает поверхность атаки, за которую мы отвечаем: мы не запускаем ОС, веб-сервер или среду выполнения приложения, которые мы должны патчить.
Применяется отдельное промежуточное ПО public-CORS Access-Control-Allow-Origin: * к следующему заданному пути: /embed.js, /embed/v1.js, всё под /embed/; /api/v1/telemetry; /api/v1/openapi.json; всё под /api/v1/qub/ (включая подпути bytes, metadata, proof, engagement, notify и push); всё, что находится под /api/v1/log/; общедоступные поиска обработчиков в рамках /api/v1/handle/; и публичный аватар читает ниже /api/v1/identity/avatar/. Его разрешения на предполетную проверку GET, POST, и OPTIONS с Content-Type заголовок запроса. Этот поверхностный слой на основе префикса шире, чем только вызовы, которые встраивание делает в данный момент, поэтому каждый обработчик ниже этих префиксов должен продолжать обеспечивать собственную проверку, аутентификацию, ограничения по скорости и меры против злоупотреблений. Другие пути API сохраняют политику CORS, ограниченную qub.social.
5.2 Хранилище
- Хранилища метаданных и координации хранить записи идентичности и аттестации, права и ссылки на выставление счетов, записи ключей API, записи в черный список, сессии, состояние идемпотентности, очереди и состояние ограничения скорости / параллелизма. Разные потребности в согласованности используют KV, D1 и Durable Objects вместо одного универсального хранилища.
- Наш хранилище объектов также является прочной подложкой. Она удерживает точно те же упакованные или необработанные квантовые байты, подтвержденные загрузкой, листами журнала прозрачности и узлами Меркле с координатным ключом, анкерным материалом, структурированными журналами событий и кешами ответов/метаданных.
- Постоянное общественное хранилище содержит якоря журнала прозрачности и, для пути T3 или отложенной публикации, отдельные транзакции qub. Мы не управляем этой сетью. Частные браузерные полезные нагрузки там остаются непрозрачными, если у держателя нет K; публичные/открытые полезные нагрузки сознательно не имеют этого дополнительного уровня возможности связи.
Поток сообщений браузера по умолчанию не сохраняет открытый текст на инфраструктуре qub. Builder /api/v1/seal обрабатывает открытый текст и K в памяти, но не сохраняет ни то, ни другое. Этап подготовки Pact обязательно сохраняет подписанный структурированный pact до тех пор, пока он не будет подписан совместно, отозван или не истечет. Включенное по желанию восстановление сохраняет возможность доставки (полную ссылку с фрагментом), чтобы ее можно было восстановить позднее. Поэтому мы не описываем весь уровень хранения как «только метаданные».
5.3 Секреты
Секреты (подпись кошельков, токены провайдера и ключи HMAC) предоставляются через привязки секретов/окружения платформы, а не через систему контроля версий. Компоненты во время выполнения получают только те привязки, которые им необходимы. Процедуры ротации и наложения зависят от конкретного компонента; мы не заявляем о существовании единого универсального автоматического или аудируемого механизма ротации.
5.4 Логирование и телеметрия
Структурированные JSON-логи пишутся при каждом API-запросе с correlation ID, выводимым в заголовке ответа X-Request-Id. Клиентская телеметрия анонимна — никакого идентификатора устройства, никакого IP-адреса, никакого превью контента. События буферизуются в памяти и сбрасываются на best-effort-основе; неудачный сброс отбрасывается, не повторяется. Телеметрия спроектирована так, чтобы её можно было отключить на сетевом уровне без влияния на продукт.
6. Аутентификация
6.1 Magic-link вход
Вход выполняется с использованием одноразового токена, подписанного HMAC, который доставляется на вашу электронную почту. Ссылка действительна в течение 15 минут, и использование токена производится атомарно, поэтому одновременное или повторное использование не допускается. В случае успеха браузер получает непрозрачный __Host-qub_session печенье с Secure, HttpOnly, SameSite=Strict, и Path=/ атрибуты.
Сессии имеют 30-дневный лимит бездействия и 90-дневный абсолютный лимит, обновляются каждые 24 часа и принимают только предыдущую генерацию в течение 120 секунд после потери ответа. Для чувствительных изменений аккаунта требуется аутентификация в течение последних 10 минут. Секрет подписи HMAC привязан к платформе; только чтение метаданных само по себе не создает действительный токен.
6.2 API-ключи (тариф разработчика)
API-ключи разработчика используют префикс qub_sk_ для лёгкого распознавания и поиска по grep. Каждый ключ:
- Привязан к учетной записи, областям и необязательному списку разрешенных IP CIDR
- Показано в исходной форме один раз; постоянные записи сохраняют его SHA-256 хеш, а не секрет обладателя
- Может быть повернут с часовым периодом перехода, в течение которого старый ключ перенаправляется на замену
- Имеет независимую квоту и состояние ограничения скорости
- Никогда не записывается полностью; журналы фиксируют только ключевой идентификатор
Административные эндпоинты управления ключами защищены отдельными административными учётными данными.
6.3 Email-аттестация (подписание авторства)
Привязка email-адреса к подписному ключу требует:
- Обладания приватным подписным ключом (Вы подписываете challenge)
- Обладания почтовым ящиком email (Вы вводите 6-значный код, доставленный email)
Любого из них в отдельности недостаточно. Отзыв — это подписанная запись в Вашем собственном аккаунте и вступает в силу немедленно; просмотровщики, извлекающие аттестацию, видят отозванное состояние и отображают соответствующим образом.
7. Платежи
Ввод и обработка карты выполняются внутри оформленного в Stripe процесса оплаты. Мы никогда не получаем номера карт, даты истечения срока действия или CVC. Мы сохраняем идентификаторы клиентов и подписок Stripe, состояние подписки и данные о периоде в записях прав/ключей API, чтобы можно было согласовать доступ, продления, измерение использования, отмену и возвраты. Политики конфиденциальности и безопасности Stripe регулируют обработку платёжных данных.
Эндпоинт запечатывания перекрёстно проверяет запись права относительно идентификатора устройства и, для авторизованных пользователей, относительно привязанной идентичности. Право не может быть переиспользовано между устройствами без явного восстановления пользователем через magic-link вход.
8. Устойчивость к злоупотреблениям
8.1 Обнаружение ботов
Поток запечатывания защищён альтернативой CAPTCHA, сохраняющей приватность, которая не использует cookies для отслеживания и не делает «отпечаток» для рекламы. Неудачный challenge отвергается нашим edge Worker до того, как произойдёт какая-либо обработка на стороне запечатывания.
8.2 Ограничение скорости
Ограничения скорости применяются на нескольких слоях:
- Ограничения по IP и по ключу на эндпоинтах запечатывания, чтения и аутентификации
- Ограничения по email на запросы magic-link (предотвращает заваливание почтового ящика)
- Ограничения по контрагенту на письма-приглашения пактов (десять на адрес получателя за UTC-сутки, основная мера против ретрансляции спама; честные пакты почти никогда не подходят к лимиту)
- Ограничения по IP на отправку телеметрии
Счётчики и атомарные операции распределяются между KV, Durable Objects и привязками платформенного ограничения скорости в соответствии с требованиями консистентности конечной точки. Запросы с ограничением скорости возвращают 429; конечные точки, которые могут вычислять окно повторной попытки, включают Retry-After.
8.3 Модерация контента
Маршрут загрузки через браузер по умолчанию не может сканировать тело: он получает только клиентский зашифрованный артефакт. Строитель /api/v1/seal маршрут временно видит открытый текст, а этап подготовки пакта хранит структурированные условия до его завершения, но эти исключения доверия не превращают общий путь загрузки байтов, слепой к содержимому, в сканер содержимого. Оперативная модерация является черный список на уровне просмотровщика: упомянутый в черном списке qub отклоняется нашим просмотровщиком независимо от того, остаётся ли доступным сохранённый полезный нагрузочный поток. Внесение в черный список не отменяет надёжные байты, записи в журнале прозрачности или данные постоянной сети, которые уже были опубликованы.
Жалобы на злоупотребления ограничиваются по скорости с использованием одностороннего хеша IP заявителя; мы не храним IP в открытом виде для этой цели.
9. Цепочка поставок и целостность сборки
9.1 Закрепление цепочки инструментов
Версии компилятора и среды выполнения зафиксированы в конфигурации репозитория, а зависимости разрешаются через зафиксированные lock-файлы. CI проверяет актуальность сгенерированных файлов и инварианты, чувствительные к воспроизводимости. Мы не делаем более сильного утверждения, что каждая чистая сборка идентична бит в бит на всех поддерживаемых машинах.
9.2 Линты и статический анализ
Workspace включает наши строжайшие группы линтов на уровне deny. CI рассматривает каждое предупреждение — включая предупреждения о ссылках в документации — как сбой сборки. Это сознательно: мы используем строгость линтов как растяжку для тонких регрессий.
9.3 Шлюзы CI
CI-воркфлоу охватывает форматирование и строгие линтеры; тесты Rust, WASM/браузер, Worker, embed и API; проверку типов; покрытие кода; проверки мутаций/инвариантов; статический анализ зависимостей и воркфлоу; проверки ключей i18n, покрытия, дрейфа и вредоносных кодовых точек; свежесть сгенерированной документации/API/базы знаний; проверку инвентаря документов и внутренних ссылок; бюджеты стилей и сборок; и валидацию OpenAPI. Некоторые ресурсоёмкие задания по мутациям планируются, а не выполняются при каждом пуше.
Один обязательный ci сводка остаётся красной, если любая необходимая задача не выполнена. Рабочие процессы защищённой ветки и развертывания используют этот результат, а не дублируют меньший этап проверки безопасности.
9.4 Mutation testing
Еженедельная задача запускает mutation testing против security-критичных чистых модулей: хеширования, канонического CBOR, seal, unlock, wire-format newtypes, валидаторов типов протокола и handle-namespace. Mutation testing отвечает на «улавливает ли наш набор тестов тонко неправильный код?» — если мутированная реализация всё равно проходит все тесты, мы знаем, что у нас есть пробел в покрытии тестами, и устраняем его.
9.5 Git hooks
Локальные хуки (pre-commit, pre-push) зеркалят шлюзы CI, так что регрессии ловятся до того, как покинут машину разработчика. Хуки устанавливаются через скрипт репозитория; они не обходятся в нашем рабочем процессе, а CI является авторитетным шлюзом, если их пропустить.
10. Тестирование
Security-критичный код несёт три вида тестов:
- Юнит-тесты проверяют ожидаемое поведение на известных входах, включая тестовые векторы, выведенные из спецификации протокола.
- Property-тесты генерируют тысячи произвольных входов и утверждают инварианты: round-trips канонического CBOR, round-trips проверки подписи, предикаты привязки email, детерминизм подтверждения пакта.
- Кросс-имплементационные тесты проверяют, что наши клиентская и серверная реализации согласуются побайтово по каноническим кодировкам. Это ловит расхождение между двумя реализациями до того, как оно достигнет продакшена.
11. Гигиена веток и релизов
Фичевые ветки продвигаются staging только через запрос на вытягивание Gate 1: обязательно ci зелёный, нет нерешённых запросов на изменения, нет конфликтов слияния и чистое проверенное дерево; слияние выполняется с объединением и удалением. main продвигается только через Ворота 2 staging → main pull request и сохраняет родословную с помощью коммита слияния. Прямые push на ветку не являются рабочим процессом выпуска.
Развертывание на промежуточной и боевой средах запускается из соответствующей защищённой staging и main ветки состояния после CI. Код pull-request и учетные данные форка не получают секреты развертывания.
Секреты, используемые в деплой-воркфлоу, ограничены окружением деплоя нашей CI-платформой. Они не доступны воркфлоу pull-request из форков.
12. Координированное раскрытие
Если Вы полагаете, что нашли уязвимость безопасности в qub, мы хотим узнать об этом быстро и обязуемся профессионально обработать отчёт.
- Напишите на
support@qub.socialс префиксом темы[SECURITY]. - Опишите уязвимость, шаги воспроизведения и любой proof-of-concept.
- Дайте нам разумное окно раскрытия (обычно 90 дней) до публичного оглашения.
- Не получайте доступ к данным, которые Вам не принадлежат, не деградируйте сервис для других пользователей и не сохраняйте полученные в ходе исследования данные сверх того, что необходимо для демонстрации проблемы.
Мы подтверждаем получение в течение трёх рабочих дней и держим Вас в курсе хода нашего расследования. С Вашего согласия мы упоминаем заявителей в release notes.
12.1 Safe Harbor
Если Ваше исследование следует приведённым выше правилам (добросовестное исследование, никакого вреда другим пользователям или сервису, разумное окно раскрытия), мы не будем предпринимать против Вас юридических действий и не будем просить об этом правоохранительные органы. Мы рассматриваем Вашу работу как уполномоченное тестирование, и мы предпочли бы, чтобы баг нашли Вы, а не кто-то ещё.
Этот Safe Harbor применяется к:
- Исследованию live-сервиса qub.social (не на тестовых фикстурах, которые мы публикуем для этой цели).
- Обратной разработке наших публикуемых бинарных файлов и open-source-крейтов qub-core / qub-app.
- Любому классу уязвимостей — протокольных, прикладных, инфраструктурных, в цепочке поставок — который затрагивает qub.
Он не применяется к социальной инженерии членов команды qub, тестам отказа в обслуживании или доступу к данным других пользователей сверх того, что необходимо для демонстрации проблемы. Если Вы не уверены, попадает ли что-то под Safe Harbor, спросите заранее с тем же префиксом темы [SECURITY].
13. Честные ограничения
Безопасность — это практика, а не состояние. Некоторые ограничения стоит назвать прямо:
- Мы — маленькая команда. Глубина нашего ревью не сравнима с выделенной функцией безопасности приложений крупной корпорации. Мы компенсируем это строгими автоматизированными шлюзами и минимальной поверхностью атаки, но мы не утверждаем непогрешимости.
- Постоянство хранилища — это дверь в одну сторону. Если ошибка приведёт к тому, что запечатанный контент станет расшифровываемым раньше, чем предполагалось, мы не можем это отменить. Мы относимся к потоку запечатывания с соразмерной осторожностью.
- Сеть drand — внешняя зависимость. Катастрофический сбой drand повлиял бы на поведение раскрытия каждого qub. Мы мониторим здоровье drand и имеем документацию аварийных действий для миграции цепочки при необходимости. Для дат раскрытия более чем через 2 года модальное окно подтверждения в момент запечатывания показывает явное раскрытие: длинно-горизонтные qubs зависят от долговечности цепочки drand, а будущая миграция цепочки drand может потребовать шагов восстановления для разблокировки qub. Для дат раскрытия более чем через 5 лет Вы должны поставить дополнительный флажок, подтверждающий, что Вы прочитали и принимаете этот риск, до того как запечатывание продолжится.
- Криптографические примитивы, на которые мы полагаемся, стандартизованы и широко проревьюированы, но криптография эволюционирует. Где у нас есть выбор (постквантовое подписание, аутентифицированное шифрование), мы выбираем более консервативный вариант.
14. Изменения настоящей страницы
Существенные изменения отмечаются обновлением даты вступления в силу в верхней части. Где изменение отражает конкретное улучшение безопасности, мы кратко описываем его в публичном changelog. Где изменение отражает уточнение политики, мы описываем, что изменилось и почему.
По вопросам о чём-либо на этой странице напишите на support@qub.social с префиксом темы [SECURITY].
15. Журнал изменений
| Версия | Дата вступления в силу | Резюме |
|---|---|---|
| 1.1 | 23 сентября 2026 | Согласованы криптографические утверждения, режимы доставки, хранение, CSP, сессии, API-ключи, платежи, CI и процесс выпуска с реализованной системой. |
| 1.0 | 2 мая 2026 | Первоначальная публикация. |