# Безопасность

> Узнайте, как Paymos защищает балансы токенов изолированной подписью выводов, белым списком адресов, HMAC-аутентификацией, подписанными вебхуками и аудитом.

Paymos — кастодиальный шлюз: мы держим ключи, которыми ваши средства двигаются в блокчейне. У любого мерчанта тут законный вопрос: **что мешает Paymos забрать мои деньги — и что будет, если что-то сломается?**

Эта страница отвечает на оба — сначала коротким списком обещаний, потом простым языком с объяснением, почему так. Здесь — гарантии платформы и то, что каждая из них вам даёт, а не «чертёж» внутренностей. То, что относится к публичному API (как подписать запрос, как проверить вебхук), описано точно — без этого не подключиться.

---

## Почему ваши деньги в безопасности

### Контроль адресов и изолированная подпись

- **Изолированная инфраструктура подписи.** Paymos исполняет кастодиальную подпись вне публичного веб-контура. Это управляемое хранение, а не прямой контроль ключей со стороны бизнеса.
- **Белый список включён по умолчанию.** Деньги уходят только на адреса, которые вы одобрили заранее, и даже полный угон API-ключей не позволит вписать новый адрес для вывода. Отключить список можно только по запросу владельца через поддержку — и тогда этой защиты нет: тот, кто получит доступ к аккаунту или ключу Payout, выведет средства на свой адрес.
- **Кто одобряет получателя и кто двигает деньги — разные права.** Белый список правит только владелец аккаунта. Роль «Финансы» отправляет выводы, но вписать в список новый адрес не может: тот, кто двигает деньги, работает по списку, который утвердил не он. При отключённом списке этой границы нет: адрес получателя вписывает тот, кто отправляет вывод. Любая выдача прав пишется в журнал.
- **Вывод — по вашему графику.** Баланс ваш с момента финальности платежа. Мы не блокируем средства. Выводите хоть раз в час, хоть никогда: между запросом и отправкой транзакции нет ни расчётного окна, ни очереди, а дальше время в пути определяет сама сеть.
- **Раздельные балансы.** Баланс каждого мерчанта учитывается отдельно. Мы не складываем средства в общий котёл и не пускаем их в оборот.

### Деньги не пропадут незаметно

- **На баланс попадают платежи с глубиной подтверждения, выбранной по сети и сумме** — достаточной, чтобы реорг был редкостью, но не такой, чтобы называть его невозможным.
- **Никаких откатов.** Подтверждённый платёж не отменяется. Если он всё же выпадет из цепочки при реорге, **убыток берёт Paymos, а не вы.**
- **Вывод не уйдёт дважды.** У каждого вывода есть ваш ключ идемпотентности.
- **Многоуровневые заморозки** могут автоматически остановить один актив, если картина в блокчейне разойдётся с учётом.
- **Вывод сверяется с вашим балансом до приёма** — если суммы вместе с комиссией сети на балансе нет, ошибка приходит сразу, а вывод не создаётся.
- **Записи, которые не подделать:** каждое значимое действие попадает в аудит, а секреты и подписи вычищаются из записи до её сохранения.

:::info
**Никаких откатов.** Подтверждённый платёж не отменяется. Если он всё же выпадет из цепочки при реорге, убыток берёт Paymos, а не вы.
:::

Дальше — каждый пункт простыми словами. Если встречали слова HMAC или SSRF и хотелось понять, что это, — читайте ниже.

---

## Модель угроз

Мы защищаемся от:

- **Средства в покое** — ключи, которыми можно двигать балансы в блокчейне
- **Средства в движении** — авторизация вывода и подмена адреса назначения
- **Доступ к API** — кража ключей, повтор запроса (replay), расширение прав
- **Доставка вебхуков** — поддельные тела запросов и использование нашей инфраструктуры как SSRF-плацдарма для атаки на вашу
- **Операционные риски** — случайные разрушительные действия, гонки между серверами, пробелы в аудите

Сознательно вне зоны ответственности: безопасность кошелька вашего клиента (ключи у него), риск на стороне получателя после подписи вывода (транзакции необратимы), сторонние сервисы рядом с Paymos и социальная инженерия против вашей команды.

---

## Подпись выводов и контроль адресов

**В чём проблема.** Средствами в блокчейне управляют ключи подписи. Украденные реквизиты, подменённый адрес или компрометация контура подписи могут привести к потере денег, если окружающие ограничения не закрываются безопасно.

**Что делает Paymos.** Исходящие транзакции подписываются в изолированной инфраструктуре. По умолчанию вывод возможен только на адрес из белого списка бизнеса, а пустой список блокирует выводы целиком. Правка списка — отдельное действие, и оно попадает в журнал аудита. Если у сотрудника подключён второй фактор, правка дополнительно потребует свежего подтверждения. Если второго фактора нет, подтверждать нечем: этот слой начинает работать в тот день, когда вы его включите. Если владелец через поддержку отключил белый список, адрес назначения ни с каким списком уже не сверяется; что остаётся в этом случае — ниже, в разделе о защите вывода.

Оператор может остановить все исходящие операции или заморозить конкретную пару актива и сети на время расследования. У каждого вывода также есть ключ идемпотентности, поэтому повтор того же запроса не создаёт второй вывод.

Инфраструктура остаётся **кастодиальной**: Paymos управляет контуром подписи. Белый список, заморозки, аудит и сверка учёта снижают риск вокруг хранения, но не превращают его в некастодиальную или пороговую модель.

У каждого инвойса есть **свой уникальный адрес** приёма, поэтому сверка однозначна. Платежи и выводы в тестовом режиме реальных средств не затрагивают — интеграцию можно проверить, не отправив ни одного настоящего перевода.

---

## HMAC — как API понимает, что запрос реально от вас

**HMAC** (*Hash-based Message Authentication Code* — «код проверки подлинности на основе хеша»). Звучит страшно, суть простая.

**В чём проблема.** Ваш сервер шлёт нам «создай вывод на 1 000 $». У нас два вопроса: это правда вы, а не самозванец? И не подменил ли кто-то запрос по дороге — сумму или адрес? Если просто класть пароль внутрь запроса, любой, кто перехватит трафик, украдёт его и будет слать запросы от вашего имени.

**Что делает HMAC.** У вас и у нас есть **общий секрет** (ваш API-секрет). На каждый запрос вы считаете «отпечаток» (подпись) — это хеш от *содержимого запроса вместе с секретом*. Шлёте запрос **и отпечаток, но не сам секрет**. Мы своим экземпляром секрета считаем такой же отпечаток. Совпало — значит, это точно вы, и **ничего не подменили**: измените хоть один символ, и отпечаток не сойдётся.

> **Аналогия.** Сургучная печать на письме. Секрет — это ваш уникальный штамп. Печать все *видят*, но **подделать без штампа не могут**. А если письмо вскрыли и переписали — печать перестанет соответствовать содержимому.

Ключевой момент: сам секрет **никогда не путешествует по сети**. Поэтому, даже записав весь ваш трафик, злоумышленник не вытащит секрет и не сделает новый запрос — у него будут лишь подписи к тем запросам, что вы и так уже отправили. *(SHA-256 — это «мельница», перемалывающая любой вход в отпечаток фиксированной длины, не раскручиваемый обратно.)*

### Точный формат (для интеграции)

Каждый аутентифицированный запрос несёт два заголовка:

```http
Authorization: HMAC-SHA256 {api_key_id}:{base64(signature)}
X-Request-Timestamp: {unix_seconds}
```

Подпись — это HMAC-SHA256 по канонической строке:

```text
{timestamp}\n{METHOD}\n{path}\n{query}\n{sha256_hex_lower(body)}
```

Пустое тело подставляется в этот слот как пустая строка — его не хешируют; параметры запроса подписываются ровно в том виде, в каком они в URL. Подробности — на странице [Аутентификация](/ru/docs/authentication.md).

### Защита от повтора (anti-replay)

А **переслать ваш старый**, записанный запрос — повторить «создай вывод» сто раз? В подпись входит метка времени, и мы отвергаем запрос, если `X-Request-Timestamp` отстаёт от времени сервера больше чем на **5 минут** или опережает его больше чем на **60 секунд** (ответ `401`). Записанный запрос живёт пять минут и умирает, а подписанный по спешащим часам — не больше чем на минуту дольше. А вместе с идемпотентностью (см. ниже) даже внутри этих минут повтор не отправит средства дважды.

> **Аналогия.** Билет с окном входа на пять минут — вчерашний не сработает.

### Сравнение «за постоянное время»

Когда мы сверяем две подписи, наивное сравнение обрывается на первом неверном символе — и по *времени ответа* можно угадать, сколько символов уже верны, и подобрать подпись по байту. Мы сравниваем **за постоянное время**: ответ «нет» занимает одинаково долго, сколько бы вы ни угадали.

> **Аналогия.** Кодовый замок, который говорит «нет» за одно и то же время — угадали вы одну цифру или пять. Понять, что «теплее», нельзя.

### Типы ключей и ротация

Два типа ключей. У каждого — жёстко закреплённый набор прав, и сервер проверяет его при каждом вызове:

- **Payment-ключ** — всё, что про деньги на входе: создавать и читать инвойсы, управлять платёжными каналами и читать их депозиты. Не может читать балансы и создавать выводы.
- **Payout-ключ** — создавать, читать и отменять выводы, читать балансы. Не может создавать инвойсы и не достаёт до платёжного канала.

Секреты меняются без простоя: вы генерируете новый, а предыдущий работает до `previous_secret_expires_at` — это ровно 24 часа с момента смены. Окно фиксированное, параметром его не задать. Пока оно открыто, принимаются оба ключа, затем — только новый.

---

## Безопасность вебхуков — тот же HMAC, только наоборот

HMAC выше защищает **ваши запросы к нам**. Вебхук — это **мы стучимся к вам** («инвойс оплачен»). Тот же приём наоборот: мы подписываем каждый вебхук секретом вашего эндпоинта, а вы проверяете подпись, прежде чем поверить. Иначе любой, кто узнает адрес вашего вебхука, мог бы прислать поддельное «оплачено» и выманить товар.

```http
X-Webhook-Signature: t={unix_seconds},v1={hex_hmac}
```

Подписывается строка `{timestamp}.{request_body}`. Схема совпадает со Stripe, поэтому библиотеки проверки от Stripe работают почти без правок; во время ротации секрета мы кладём в заголовок обе подписи, а утёкший секрет можно заменить и без этого перекрытия. См. [Проверка вебхуков](/ru/docs/webhooks/verify.md).

### Защита от SSRF

**SSRF** (*Server-Side Request Forgery* — «подделка запроса со стороны сервера»). Вы задаёте адрес вебхука, и **наши серверы** ходят на него. Хитрый злоумышленник укажет URL не наружу, а **внутрь нашей сети** — на адрес облачных метаданных или внутреннюю панель — и наш сервер сходит туда за него, превратив Paymos в «прокладку» к тому, что видно только из нашей сети.

Мы это предотвращаем: адрес вебхука проверяется на то, что ведёт на **публичный** адрес — loopback, приватные, внутренние диапазоны и метаданные отклоняются, — а соединение «прибивается» к проверенному адресу, чтобы не было окна для DNS-rebinding. Редиректы не выполняем. Адрес, не прошедший проверку, сразу отбрасывается, поэтому «прощупывать» бесполезно. Проверяется и порт: в URL вебхука допустим 443 или любой от 1024 и выше, так что доставку не направить на стандартный порт SSH, почтового сервера или другого известного сервиса на чужой машине.

> **Аналогия.** Курьер, который доставляет только на реальные внешние адреса, отказывается нести «в серверную этого же здания», проверяет адрес до выхода и не ведётся на записку «вообще-то отнеси вон туда».

### Семантика доставки

URL вебхука должен быть на **HTTPS** (проверяется при сохранении). Доставка — **не реже одного раза**: дедуплицируйте по идентификатору события на своей стороне (так делают Stripe, GitHub, PayPal). Неуспешные доставки **повторяются** с экспоненциальной задержкой — всего 11 попыток примерно за 16 часов, полное расписание см. в [Доставке и повторах](/ru/docs/webhooks/retry.md), — затем помечаются неуспешными и доступны для переотправки из дашборда. У каждой попытки свой тайм-аут.

---

## Защита вывода — несколько замков подряд

Вывод средств — самое уязвимое место кастодиального шлюза, поэтому слоёв тут больше всего:

- **Белый список (по умолчанию включён).** Пока список включён, в том числе во время рассмотрения запроса на отключение, вывод возможен только на заранее одобренный адрес. Если для семейства сетей назначения список пуст, выплату создать нельзя: первый вывод сам адрес не добавляет. Получателем может быть и ваш клиент — список не ограничен вашими кошельками. Украденный выплатной ключ не позволяет отправить средства на адрес вне списка, пока эта защита действует.
- **Отключение белого списка.** Запросить его может только владелец аккаунта, в карточке «Адреса для вывода». Детали поддержка уточнит в чате, решение примет сотрудник Paymos. Без списка вывод уходит туда, куда его направили. В дашборде адрес вводят вручную и подтверждают через 2FA, если она включена; через API выводит только рабочий ключ Payout со списком разрешённых IP, а ключу без такого списка придёт отказ с кодом `ip_allowlist_required`. Защиты при этом меньше: тот, кто получит доступ к аккаунту или ключу, сможет вывести средства на свой адрес. Включить список обратно владелец может сам и в любой момент, на странице «Баланс», — сохранённые адреса вернутся вместе с ним. Пока запрос на рассмотрении, белый список действует. Если активный рабочий выплатной ключ уже создан, для одобрения в нём должен быть хотя бы один разрешённый IP. Создавать ключ ради вывода из дашборда не требуется.
- **Роли и права на вывод.** По умолчанию управлять белым списком может владелец, а создавать выводы — владелец и участник с ролью «Финансы». У администратора этих прав по умолчанию нет; дополнительные права можно выдать отдельно, и выдача попадёт в аудит. Запросить отключение белого списка, отменить запрос или включить список обратно может только владелец: дополнительные права эти действия не передают.
- **Второй фактор (2FA).** Шестизначный код из приложения, меняется каждые 30 секунд; добавленный passkey работает вместо него. По умолчанию он выключен, и подключают его вручную — но именно он включает повторное подтверждение на опасных действиях: изменить белый список выводов, запросить его отключение, вывести на адрес, введённый вручную, поправить список разрешённых IP у API-ключа или отключить сам второй фактор без свежего кода уже не выйдет.
- **Заморозки (стоп-кран).** Можем заморозить всё сразу, один токен в одной сети или одного мерчанта. Заморозка по активу включится сама, если балансы в блокчейне разойдутся с учётом сверх безопасного порога.
- **Проверка баланса до приёма.** Сумма вывода вместе с комиссией сети сверяется с вашим доступным балансом ещё до того, как запрос принят. Не хватает — приходит `insufficient_balance`, и вывод не создаётся: ничего не повисает.
- **Идемпотентность.** Ваш идентификатор заказа — ключ идемпотентности: пришлёте его дважды — получите тот же единственный вывод, а не второй перевод. *Аналогия: номерок гардероба; сдадите его дважды — получите одно и то же пальто.*
- **Безопасность при гонках.** Параллельные запросы на вывод для одного аккаунта выстраиваются в очередь на сервере, поэтому два одновременных вызова не проскочат мимо одной проверки баланса.

---

## Авторизация и изоляция

- **Каждый запрос проверяется на сервере** перед любым действием: среда ключа должна совпадать со средой ресурса, прав ключа должно хватать на операцию, а ресурс должен принадлежать вызывающему. Интерфейс лишь показывает результат этих проверок.
- **404, а не 403.** Если ресурса нет — *или* он есть, но не ваш — вы получите `404`. Так не отличить «такой ID существует, но не твой» от «такого ID нет». *Аналогия: швейцар говорит «такого нет» и когда человека нет, и когда он есть, но вам нельзя.*
- **Кто вы — берётся из ключа, а не из тела запроса.** Подставить чужой идентификатор бесполезно: действовать от имени другого мерчанта, подменив ID, нельзя.
- **Гранулярные права.** Доступ управляется тонкими ролевыми правами (например: вывод, просмотр баланса, управление вебхуками), каждое выдаётся отдельно. Граница — серверная проверка; дашборд лишь отражает её.

---

## Ограничение частоты запросов

У каждого мерчанта свои лимиты. Превысили — приходит `429 Too Many Requests` с заголовком `Retry-After`, поэтому одна «сбойная» интеграция бьёт только по своей пропускной способности, а не по платформе и не по другим мерчантам.

---

## Финальность в блокчейне — почему «деньги не пропадут»

В блокчейне транзакция «появляется» в блоке быстро, но недавнюю историю цепочка ещё может **переписать** (реорг) — и то, что выглядело подтверждённым, исчезает. Как сырые чернила: вроде написано, но ещё может смазаться.

**Финальность** — это дождаться, пока транзакция «закопается» достаточно глубоко, чтобы откатить было нельзя. Чернила высохли. Баланс меняется только после финальности, принятой в конкретной сети. Там, где финальность измеряется глубиной подтверждений, глубина зависит от суммы: небольшой платёж закрывается быстро, крупный ждёт дольше. Там, где сеть даёт финальность сама, зачисление идёт по финальному блоку. Пороги подстраиваются под состояние сети, а не зафиксированы навсегда.

Главное обещание: если уже подтверждённый платёж всё же выпадет при реорге (большая редкость) — **убыток берёт Paymos, а не вы.** Как пришёл вебхук о подтверждении — на него можно реагировать сразу. Бонусом: **нет возвратных платежей (chargeback)** — в отличие от карт, оплату по которым покупатель отменяет много месяцев спустя. Истёкший инвойс так и остаётся истёкшим: деньги, пришедшие после срока, заново его не открывают. Если поздние переводы в токене инвойса вместе с прежними набрали нужную сумму, придёт вебхук `invoice.paid_late`, статус при этом не изменится, а выдавать ли заказ, решаете вы.

---

## Защита данных

**В пути:** весь трафик по TLS 1.2+, в рабочей среде включён HSTS, незашифрованные запросы перенаправляются на HTTPS.

**В покое:** сессионные куки — `HttpOnly`, `Secure`, `SameSite=Lax`; ссылки для входа одноразовые, быстро истекают и хранятся зашифрованными.

**Защита от подделки запроса (CSRF):** запросы на вход и на работу с сессией сервер принимает, только если они отправлены с сайта Paymos, а действия в дашборде, меняющие состояние, несут анти-CSRF-токен. Куки `SameSite=Lax` добавляют к этому ещё один слой.

**Журнал аудита:** по каждому значимому действию записывается, кто его выполнил, что именно сделано, когда и с каким результатом. Чувствительные значения — секреты, пароли, токены, хеши, подписи — затираются ещё до записи.

---

## Операционная устойчивость

- **Безопасность на нескольких серверах.** Работа в несколько серверов не приводит к повторной обработке платежа, вывода или вебхука: параллельные операции над одним объектом согласованы так, чтобы выполниться ровно один раз. Проверяется автотестами, а не «на честном слове».
- **Отчёты об ошибках без утечки данных.** Из отчётов о сбоях вычищаются персональные данные и содержимое запросов до того, как они покинут наши системы.
- **Безопасные изменения схемы.** Миграции базы применяются один раз, по порядку и только «вперёд» — без разрушительных откатов по рабочим данным.

---

## Комплаенс и работа с данными

**KYC в Paymos нет.** Начать тестирование можно без документов о личности, адресе и бенефициарах; Paymos также не собирает такие документы у ваших клиентов. В продукте нет ни анкеты, ни загрузки документов, ни отдельного шага, который открывал бы рабочий режим. Paymos не проверяет бизнес, лицензии и категории мерчантов. Зато автоматически проверяет блокчейн-адреса: с какого пришёл платёж и на какой уходит вывод. Это проверка адресов, личность ваших клиентов она не устанавливает. Обязанности по AML и санкциям остаются у мерчанта; как устроена проверка и где проходит граница, описано в [политике AML](/ru/aml).

**Данные на стороне клиента.** Изначально Paymos не собирает персональные данные ваших клиентов на странице оплаты — ни email, ни телефон, ни имя, ни данные карты. Поток: инвойс → платёжная страница → кошелёк платит → готово. Мы видим адреса кошельков и суммы, а не личности, поэтому ваши риски по GDPR/CCPA через Paymos практически нулевые.

**Данные на стороне мерчанта.** По вашему аккаунту мы храним название бизнеса, контактный email, страну и метаданные проектов (URL вебхуков, идентификаторы API-ключей). Права по GDPR, включая удаление, и адрес для запроса — в [Политике конфиденциальности](/privacy).

---

## Чего мы не делаем

- **Не заявляем то, чего не построили.** Эта страница описывает систему как она развёрнута. Планы развития не появляются здесь, пока не выпущены.
- **Не держим средства дольше, чем нужно.** Деньги на балансе с момента подтверждения; когда выводить — решаете вы.
- **Не складываем балансы в общий котёл.** Каждый баланс раздельный. Неплатёжеспособность или спор одного мерчанта не дотянется до средств другого. *Именно смешение средств в общий котёл погубило биржи вроде FTX.*
- **Не обещаем безопасность на стороне получателя.** После подписи вывода транзакция уже в блокчейне и необратима. Пока белый список включён, он спасает от опечаток и кражи ключей — но не проверит, как поведёт себя одобренный вами адрес.

---

## Сообщить об уязвимости

Присылайте на **security@paymos.io**.

- **Подтверждение получения:** в течение двух рабочих дней после полного отчёта
- **Область программы:** рабочие `paymos.io` и `*.paymos.io`, публичный REST API, опубликованные Paymos SDK и модули CMS
- **Вне области:** отказ в обслуживании через лимиты частоты, социальная инженерия, сторонние сервисы (ваш CDN, хостинг и т.п.)
- **Вознаграждение за уязвимости (bug bounty):** публичной программы пока нет; приватное раскрытие значимых находок вознаграждается индивидуально, с упоминанием по запросу.

Пожалуйста, не тестируйте на аккаунтах других мерчантов, не применяйте разрушительные техники к рабочей среде и не публикуйте находку до того, как мы успеем её починить. Со своей стороны мы подтвердим получение полного отчёта в течение двух рабочих дней, будем держать вас в курсе, упомянем вас (с вашего согласия) при выпуске исправления и не будем преследовать добросовестное исследование в рамках программы.
