# Локальная безопасность

> Требования безопасности к сервисам LMSP, включая привязку к loopback, сопряжение и Bearer-токены, области доступа, проверки Origin и Host против вредоносных веб-страниц, режим LAN и правила журналирования.

Source: https://madeforagent.com/ru/lmsp/1.0/security/
Language: ru
Specification: LMSP 1.0 (draft)
Updated: 2026-11-08

## 10.1 Базовые меры {#baseline}

Прослушивание только localhost — не абсолютная защита: вредоносная веб-страница всё равно может пытаться обратиться к локальным портам. Поэтому LMSP сочетает несколько мер.

- Сервис **ДОЛЖЕН** по умолчанию привязываться к loopback-адресам. Он **НЕ ДОЛЖЕН** слушать `0.0.0.0` или любой другой адрес, не являющийся loopback, если не включён режим LAN ([раздел 10.5](https://madeforagent.com/ru/lmsp/1.0/security.md#lan)).
- При первом запуске сервису **СЛЕДУЕТ** сгенерировать случайный секрет сервиса с высокой энтропией и использовать его, а не какое-либо встроенное значение по умолчанию, для выпуска и проверки токенов.
- Каждый запрос к основному интерфейсу **ДОЛЖЕН** нести действительный Bearer-токен, кроме начальных эндпоинтов, перечисленных в [разделе 4.2](https://madeforagent.com/ru/lmsp/1.0/endpoints.md#conventions). Одного лишь происхождения с loopback никогда не достаточно.

## 10.2 Сопряжение и токены {#pairing}

Клиент получает собственный Bearer-токен с помощью локального кода сопряжения. Пользователь просит сервис показать код сопряжения тем способом, который предлагает сервис, и клиент отправляет его:

```http
POST /lmsp/v1/pair
Content-Type: application/json
```

```json
{
  "client_name": "example-client",
  "pairing_code": "K7QD-4M2X",
  "scopes": ["inference"]
}
```

| Поле запроса | Значение |
| --- | --- |
| `client_name` | Отображаемое имя клиента, которое видит пользователь. |
| `pairing_code` | Код, который пользователь получил от сервиса. |
| `scopes` | Необязательный список запрашиваемых областей доступа. По умолчанию `["inference"]`. |

Сервис отвечает токеном. Значение `token_type` всегда `Bearer`:

```json
{
  "client_id": "cli_01J8MAT3W6X9B2D5F8H1K4N7QZ",
  "access_token": "lmsp_example_3f9a1c52e7d84b60",
  "token_type": "Bearer",
  "scopes": ["inference"]
}
```

Затем клиент отправляет `Authorization: Bearer <token>` с каждым запросом.

- Код сопряжения **ДОЛЖЕН** быть одноразовым, а срок его действия **СЛЕДУЕТ** ограничивать 5 минутами. Код **СЛЕДУЕТ** формировать так, чтобы он содержал не менее 40 бит энтропии. Сервис **ДОЛЖЕН** ограничивать частоту неудачных попыток. На неверный или просроченный код сервис отвечает `401` и `unauthorized`.
- Токены независимы для каждого клиента, поэтому пользователь может отозвать один клиент, не затрагивая остальные. Сервису **СЛЕДУЕТ** позволять пользователю просматривать список сопряжённых клиентов и отзывать их.
- Клиенту **СЛЕДУЕТ** хранить токен в связке ключей или менеджере учётных данных операционной системы. Сервису **СЛЕДУЕТ** хранить только хеш каждого токена.
- На отсутствующий, недействительный или отозванный токен сервис отвечает `401`, `unauthorized` и заголовком `WWW-Authenticate: Bearer`. На действительный токен, которому не хватает области доступа, нужной эндпоинту, сервис отвечает `403` и `forbidden`.

## 10.3 Области доступа {#scopes}

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

| Область доступа | Разрешает |
| --- | --- |
| `inference` | Чтение каталога моделей, создание ответов и задач, а также чтение и отмену собственных задач клиента. |
| `models:manage` | Загрузку и выгрузку моделей. |
| `models:install` | Зарезервировано. Скачивание и удаление моделей. |
| `tools:execute` | Зарезервировано. Выполнение инструментов на стороне сервиса. |

Задачи и сохранённые ответы принадлежат клиенту, который их создал. Сервису **СЛЕДУЕТ** отвечать на запрос другого клиента так, будто их не существует (`task_not_found` или `response_not_found`).

## 10.4 Защита браузера и сети {#browser}

- Сервис **ДОЛЖЕН** по умолчанию отклонять кросс-доменные запросы браузера и разрешать только явно настроенные значения `Origin`. На запрос с любым другим `Origin` сервис отвечает `403` и `forbidden`.
- Если источник разрешён, сервис отвечает на его предварительные запросы CORS и отправляет `Access-Control-Allow-Origin` ровно с этим источником, но никогда не с `*`.
- Сервис **ДОЛЖЕН** проверять заголовок `Host`, чтобы предотвратить DNS rebinding. Он принимает только те имена хостов, которые обслуживает: имена и адреса loopback, а также любые имена, настроенные для режима LAN. На любое другое значение сервис отвечает `403` и `forbidden`.

## 10.5 Режим LAN {#lan}

Режим LAN означает прослушивание не только loopback-адресов.

- Сервис **НЕ ДОЛЖЕН** включать режим LAN, если пользователь явно его не включил.
- В режиме LAN сервис **ДОЛЖЕН** требовать аутентификацию, а также **СЛЕДУЕТ** включать TLS. Клиенту **НЕ СЛЕДУЕТ** отправлять токен по обычному HTTP на адрес, не являющийся loopback, если пользователь явно этого не разрешил.
- Объявление mDNS разрешено только в режиме LAN, когда пользователь дополнительно включил обнаружение в локальной сети ([раздел 3.2](https://madeforagent.com/ru/lmsp/1.0/discovery.md#mdns)).

## 10.6 Журналирование и конфиденциальность {#logging}

- Пути к моделям, журналы, промпты и сгенерированное содержимое **НЕ ДОЛЖНЫ** попадать в объявления mDNS.
- По умолчанию сервису **СЛЕДУЕТ** журналировать только метаданные (время, эндпоинты, коды состояния, идентификаторы, количество токенов и длительности). Полные промпты и сгенерированное содержимое **НЕ СЛЕДУЕТ** журналировать.
- Ответы проверки работоспособности и подробности ошибок **НЕ ДОЛЖНЫ** содержать пути к моделям, промпты, токены доступа и другие чувствительные сведения.
