Для команд інформаційної безпеки та рецензентів застосунків

Безпека в Peel

Коротко: вміст дошки шифрується в браузері ключем, який міститься у фрагменті посилання, тому наші сервери зберігають і пересилають шифротекст, який не можуть прочитати. Нижче — як саме це працює і де пролягають межі.

Підсумок

  • Текст карток, імена, назви дошок, голоси та стікери шифруються алгоритмом AES-256-GCM ключем дошки, згенерованим у браузері. Ключ передається у фрагменті URL (#k=) і ніколи не надсилається на сервер.
  • Дії фасилітатора, заголовок дошки та знімки стану підписуються ключем фасилітатора Ed25519. Ідентифікатор дошки виводиться з цього ключа, тож клієнти виявляють підміну ключа.
  • Приховані картки запечатані для фасилітатора (X25519 sealed box) до відкриття і прив’язані солоними зобов’язаннями (commitments), тож відкритий текст неможливо підмінити.
  • Анонімно за замовчуванням: операції не містять ідентифікатора автора; голоси й реакції використовують випадковий ідентифікатор, окремий для кожної дошки.
  • Учасники ніколи не автентифікуються. Жодних SDK аналітики, реклами чи сторонніх скриптів, окрім Paddle.js на сторінці оплати.
  • Лише Cloudflare. Незакріплені дошки видаляються через 60 днів після останнього відвідування.

Як рухаються дані

Фрагмент URL (усе після #) обробляє браузер, і він не входить до HTTP-запиту. Саме туди Peel кладе ключ дошки.

Потік даних: ключ зчитується з посилання локально; мережею передаються лише шифротекст і мінімум метаданих.

Модель загроз

Ми проєктуємо систему так, щоб повністю скомпрометований або надто цікавий сервер — зокрема й ми самі — дізнавався якомога менше про те, що каже команда.

Що ми захищаємо

  • Текст карток, вибір GIF і, в іменному режимі, ім’я автора.
  • Імена й аватари учасників, назву дошки та назви власних шаблонів.
  • Хто за що голосував чи на що реагував і хто яку картку написав.
  • Цілісність ретро: етапи, відкриття та рішення фасилітатора неможливо підробити.

Кого ми вважаємо зловмисниками

  • Наші власні сервери, недобросовісний інсайдер або той, хто зламав наше сховище: вони отримують шифротекст і метадані.
  • Атакувальник у мережі: TLS усюди; ключ ніколи не передається мережею.
  • Сервер, що підміняє ключі: ідентифікатор дошки виводиться з публічного ключа фасилітатора, а клієнти перевіряють підписаний заголовок.
  • Учасник, який хоче підглянути чи підробити: приховані картки запечатані для фасилітатора; операції фасилітатора потребують його підпису; редагування картки потребує ключа картки.
  • Фасилітатор, що повторно публікує картку за автора, який офлайн: зобов’язання не дають змінити текст.

Чесно: що поза межами моделі

  • Будь-хто з посиланням учасника може читати дошку. Посилання — це і є контроль доступу. Поширюй його так само обережно, як саму дошку.
  • Скомпрометований пристрій, шкідливе розширення браузера або хтось, хто зазирає через плече.
  • Аналіз трафіку: сервер бачить час, розміри та лічильники (див. карту даних).
  • Відмова в обслуговуванні з боку сервера: він може відкидати чи затримувати повідомлення, але не читати й не підробляти їх.

Криптографія

Усі примітиви — з браузерного API WebCrypto. Жодної саморобної криптографії, жодних сторонніх криптобібліотек.

КлючАлгоритмПризначення
K_boardAES-256-GCM, випадковий 96-бітний IVШифрує кожну операцію, знімок стану й оновлення присутності. Додаткові дані (AAD) прив’язують ідентифікатор дошки, тип операції та її ідентифікатор, тож шифротекст неможливо повторно відтворити в іншій дошці чи слоті. Існує лише у фрагменті посилання #k=.
K_ownerEd25519Повноваження фасилітатора. Підписує операції фасилітатора (етап, таймер, фокус, шаблон, налаштування, відкриття голосів, приховування картки), заголовок дошки та знімки стану. Строго зростаючий лічильник блокує повторне відтворення. Лише в посиланні фасилітатора (&o=).
Ідентифікатор дошкиSHA-256, перші 80 біт, base32Виводиться з публічного ключа фасилітатора, тож сам ідентифікатор доводить, якому ключу належить дошка. Клієнти відхиляють заголовок, ключ якого не дає цей ідентифікатор після гешування.
K_facX25519 sealed box: ефемерний X25519 + HKDF-SHA256 + AES-256-GCMПоки учасники пишуть, приховані картки запечатуються публічним ключем фасилітатора. Відкрити їх можна лише з посиланням фасилітатора (&f=).
Ключі картокEd25519, окремий ключ для кожної карткиЄ лише в автора. Ним підписуються редагування та відкриття: автентичність без розкриття особи.
Зобов’язанняHMAC-SHA256 із випадковою 128-бітною сіллюПрихована картка публікує зобов’язання щодо свого вмісту. Під час відкриття публікуються вміст і сіль, і кожен клієнт їх перевіряє, тож ніхто не може підмінити текст.
ПрисутністьAES-256-GCM ключем K_boardІмена, аватари та індикатори набору тексту шифруються так само, як і все інше.
Пакет ключівHKDF-SHA256 із PRF ключа доступу (passkey) або коду відновлення, AES-256-GCMФасилітатори з акаунтом можуть синхронізувати ключі дошок між пристроями. Пакет шифрується на пристрої; сервер зберігає лише шифротекст і обгорнуті ключі.

Підписувані повідомлення розділено за доменами (наприклад, peel/sig/v1, peel/header/v1, peel/snap/v1), тож підпис для однієї мети неможливо використати для іншої.

Приховані картки й відкриття

  1. Поки автор пише, його браузер запечатує картку ключем X25519 фасилітатора й публікує солоне зобов’язання. Відкритий текст залишається на пристрої автора.
  2. Інші учасники бачать приховану картку: вони не можуть її розшифрувати, як і сервер.
  3. Браузер фасилітатора може відкривати запечатані картки (попередній перегляд «👁 лише ти»).
  4. Під час відкриття кожен автор повторно публікує картку, зашифровану ключем K_board і підписану ключем картки, разом із сіллю.
  5. Якщо автор офлайн, фасилітатор публікує картку за нього. Кожен клієнт перевіряє зобов’язання, тож текст має збігатися з тим, що написав автор.

Оскільки фасилітатор технічно може переглядати картки, поки вони приховані, кожна дошка показує всім позначку «фасилітатор може переглядати». Це не налаштування, і приховати її неможливо.

Анонімність

  • Операції не містять ідентифікатора автора. Сервер не може пов’язати картку з людиною, і за замовчуванням фасилітатор теж.
  • Голоси й реакції прив’язані до випадкового ідентифікатора, окремого для кожної дошки й не пов’язаного з іменем.
  • Індикатори набору тексту показують, що хтось пише, але ніколи — що саме.
  • Іменний режим — це явне налаштування дошки; у ньому ім’я автора передається всередині зашифрованої картки.
  • Учасники ніколи не входять в акаунт, тож немає жодного акаунта, який можна було б зіставити.

Карта даних

Усе, що ми зберігаємо: де це лежить, хто може це прочитати і як довго воно зберігається.

ДаніДеХто може прочитатиТермін зберігання
Картки, голоси, реакції, стікери, дії, назва дошки, назви власних шаблонівСховище Durable Object, у вигляді шифротекстуТі, хто має посилання на дошкуДоки дошку не видалено
Обгортка операції: тип, серверний порядковий номер і час, розмір, лічильник фасилітатораСховище Durable ObjectPeelДоки дошку не видалено
Імена учасників, аватари, індикатор наборуПересилається як шифротекст; зберігається в пам’яті під час з’єднанняТі, хто має посилання на дошкуПоки триває з’єднання
Статус дошки: етап, кількість учасників і карток, ідентифікатор шаблону з каталогу, позначка блокування, час створення й завершення строкуDurable Object, D1; повідомлення в Slack/Teams, якщо встановленоPeel; ваш канал у Slack/TeamsПротягом життя дошки
Акаунт фасилітатора: ідентифікатор у провайдера, ім’я, email (якщо надано), пов’язані провайдери, дата створення, сесіяD1PeelДоки акаунт не видалено
Пакет ключів і обгорнуті ключіD1, у вигляді шифротекстуЛише власник (ключ доступу або код відновлення)Доки акаунт не видалено
План, статус підписки, ідентифікатори клієнта й підписки в PaddleD1; PaddlePeel, PaddleСтільки, скільки вимагає податкове законодавство
Ідентифікатори робочого простору, каналу й повідомлень у Slack/Teams; токен бота (зашифрований AES-GCM)D1PeelДоки застосунок не видалено
IP-адресаПериферія Cloudflare, тимчасово (доставка, обмеження частоти запитів)Cloudflare, обмежувач частоти запитів PeelНе зберігається в наших базах даних
Щоденні лічильники (створені дошки, пройдені етапи)D1PeelЛише агреговано, без ідентифікаторів

Що наш сервер може і чого не може

Він може

  • Бачити типи операцій, розміри, час, етап, кількість учасників і карток, ідентифікатор шаблону з каталогу та позначку блокування.
  • Відкидати, затримувати операції чи відмовлятися їх доставляти (відмова в обслуговуванні).
  • Бачити IP-адреси на периферії мережі.
  • Рахувати дошки та пройдені етапи в агрегованому вигляді.
  • Видалити дошку (завершення строку, скарги на зловживання).

Він не може

  • Читати текст карток, імена, назви дошок, назви власних шаблонів, голоси чи стікери.
  • Читати приховані картки до відкриття (і навіть після нього).
  • Підробляти дії фасилітатора: для них потрібен підпис фасилітатора.
  • Підставити власні ключі: ідентифікатор дошки це викаже.
  • Змінити відкритий текст картки: зобов’язання й підписи карток це викажуть.
  • Визначити, хто яку картку написав.

Як і з будь-яким вебзастосунком, ви довіряєте коду, який ми віддаємо. Ми тримаємо цю поверхню мінімальною: сувора політика Content Security Policy, script-src обмежений нашим власним джерелом, жодних сторонніх скриптів, а протокол відкритий для аудиту на запит.

Slack і Microsoft Teams

  • Повідомлення містять посилання на дошку та метадані (назва, етап, лічильники). Текст карток надсилається лише тоді, коли фасилітатор публікує підсумок і підтверджує це.
  • Картка «Приєднатися» містить посилання учасника разом із ключем. Будь-хто, хто читає канал, може приєднатися — так само, як якщо вставити туди посилання.
  • Розгорнуті прев’ю посилань показують лише етап і лічильники, ніколи не вміст.
  • Дозволи Slack: commands, chat:write, links:read, links:write; users:read — лише якщо команда вмикає згадки.
  • Токени ботів зберігаються в зашифрованому вигляді (AES-GCM, ключ зберігається як секрет Worker). Підписи запитів Slack і токени Bot Framework перевіряються в кожному запиті.
  • Видалення застосунку зупиняє всі публікації та видаляє його токени.

Веб та інфраструктура

  • Лише Cloudflare: Pages, Workers, Durable Objects, D1, R2 і KV в акаунті 1801 Labs. Жодних інших серверів.
  • TLS усюди, HSTS і сувора політика Content Security Policy.
  • Жодних SDK аналітики, реклами чи сторонніх скриптів. Єдиний виняток — Paddle.js, який завантажується лише на сторінці оплати.
  • Одне cookie, лише для фасилітаторів, які увійшли: peel_session, httpOnly, Secure, SameSite=Lax.
  • Пошук GIF і медіа проходять через наш API, тож IP-адреси учасників ніколи не потрапляють до GIPHY.
  • Шрифти й ресурси розміщені на наших серверах. Жодних шрифтів із CDN, жодних пікселів відстеження.
  • Обмеження частоти запитів для кожної IP-адреси й кожної дошки; скарги на зловживання та блокування дошки фасилітатором.

Акаунти та зберігання даних

  • Учасники ніколи не автентифікуються. Фасилітатори входять через Google (чи Entra ID через Teams) лише для того, щоб зберігати дошки або користуватися платними функціями.
  • Акаунт зберігає ідентифікатор, ім’я та email від провайдера, а також зашифрований пакет ключів, який розблоковується ключем доступу (WebAuthn PRF) або кодом відновлення. Вхід в акаунт дає право власності, а не доступ до вмісту.
  • Закріплення дошки за акаунтом підтверджує право власності підписом фасилітатора. Ключі дошки ніколи не надсилаються.
  • Дошки без акаунта видаляються через 60 днів після останнього відвідування; кожне відвідування запускає відлік заново. Сховище видаляють будильники Durable Object.
  • Видалення акаунта видаляє сесії, пакет ключів і бібліотеку та повертає дошкам 60-денний строк зберігання.

Відповідальне розкриття

Знайшли вразливість? Повідомте спершу нам, і ми розберемося разом. Ми підтверджуємо отримання звітів протягом трьох робочих днів.

[email protected]

  • Будь ласка, дайте нам розумний час на виправлення (ми прагнемо вкластися в 90 днів), перш ніж розкривати інформацію.
  • Тестуйте на власних дошках і акаунтах. Не отримуйте доступу до чужих даних і не погіршуйте роботу сервісу.
  • Ми не переслідуватимемо в судовому порядку сумлінні дослідження, що відповідають цим правилам.
  • Машинозчитуваний контакт: /.well-known/security.txt.

Клієнти плану «Компанія» отримують пакет для перевірки безпеки (відповіді на опитувальники, субпроцесори, потоки даних). DPA · Конфіденційність