AACsearch
Безопасность и соответствие

Белый список по источнику (Origin)

Ограничение, с каких веб-источников можно пользоваться браузерным API-ключом.

Allow-list по Origin

Если API-ключ лежит в браузерном коде — считайте, что прочесть его может кто угодно. Allow-list по Origin делает этот сценарий допустимым: AACsearch отбрасывает запросы, у которых заголовок Origin не входит в список, настроенный для ключа.

Это не CORS. CORS управляет тем, разрешит ли браузер прочитать ответ. Allow-list по Origin — серверная проверка, которая отбрасывает запрос до выполнения поиска, независимо от того, браузер ли отправил запрос.

Модель безопасности браузера

Браузерный поиск держится на трёх слоях, которые работают вместе:

  1. Allow-list по Origin — ключом можно пользоваться только с ваших доменов.
  2. Scope search — ключ не может мутировать данные даже с вашего домена.
  3. Жёсткий rate limit в минуту — ограничивает злоупотребления с одного клиента.

Для пер-юзер фильтрации добавьте четвёртый слой: Scoped-токены.

Настройка allow-list

В дашборде:

  1. Project → API keys → Create key (или редактирование существующего).
  2. В Allowed origins — по одному источнику в строке. Origin — это scheme://host[:port], без пути, без слеша в конце, без подстановок.
  3. Сохраните.

Примеры:

https://shop.example.com
https://www.example.com
https://staging.example.com:3000

Для локальной разработки добавьте http://localhost:3000 (или ваш порт). Уберите его из боевого ключа перед выкаткой.

Как идёт сверка

На каждом публичном запросе сервер берёт заголовок Origin и сверяет с allow-list — точное, регистрозависимое равенство. Если список непуст, а заголовок отсутствует или не совпадает — HTTP 403 origin_not_allowed.

Если список пуст — проверка не выполняется. Это правильный дефолт для серверного ключа (его не вызывает ни один браузер). И неправильный дефолт для браузерного ключа.

Браузер шлёт:                        Сервер сверяет:
Origin: https://shop.example.com  →  allowedOrigins.includes("https://shop.example.com") ?
                                       да    → продолжаем
                                       нет   → 403 origin_not_allowed

Сравнение — O(n) по короткому списку. Никаких startsWith, подстановок, regexp. Если нужен *.example.com — перечисляйте поддомены.

Когда применять

Где используется ключAllow-list?
Браузер (виджет, ваш JS)Обязательно. Без него ключ ничем не ограничен.
Мобильное приложение (native HTTP)Не нужно — приложение не шлёт браузерный Origin.
Серверный воркерНе нужно. Используйте серверный ingest / admin ключ.
CMS-коннектор (PrestaShop, Bitrix)Не нужно. ss_connector_* — серверные.

От чего allow-list не защищает

  • От украденного ключа. Серверный атакующий вообще не пошлёт Origin — и получит 403. Но если он запускает реальный браузер на разрешённом домене (XSS, вредоносное расширение), Origin корректный и запрос пройдёт. Здесь работают остальные слои (scope search, rate limit, scoped-токен).
  • От уязвимого расширения. Расширения иногда инжектят скрипты на ваши страницы. CSP и жёсткий scope снижают эффект.
  • От XSS на вашем домене. Если у сайта XSS, атакующий ходит к API с вашего же origin. Чините XSS.

Частые ошибки

  • Слеши и пути. https://example.com/https://example.com. В заголовке Origin пути нет — уберите.
  • Забыли staging / preview. Если preview-окружение крутится на другом хосте (pr-123.preview.example.com), проверка упадёт. Либо отдельный ключ на окружение, либо включите preview-хосты.
  • Один ключ в мобильном приложении. Нативное приложение не шлёт Origin — строгий allow-list его отвергнет. Заводите отдельный ключ или оставляйте список пустым на мобильном и опирайтесь на другие слои.
  • Origin: null. Песочные iframe и file://-страницы шлют Origin: null. null совпадает, только если он явно в списке — обычно не нужно.

Пример: продакшн-настройка

Имя ключа:           Frontend Search (prod)
Scopes:              search
Allowed origins:     https://example.com
                     https://www.example.com
Rate limit:          600 / минута / ключ
Индексы:             products, articles

Этот ключ, утёкший из бандла, можно использовать только с example.com или www.example.com. Записать он ничего не сможет, а пики выше 600 запросов в минуту режутся до Typesense.

См. также

On this page