# Seguridad local

> Requisitos de seguridad para los servicios LMSP, con enlace a loopback, emparejamiento y tokens de portador, ámbitos, comprobaciones de Origin y Host frente a páginas web maliciosas, modo LAN y reglas de registro.

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

## 10.1 Línea base {#baseline}

Escuchar solo en localhost no es seguridad absoluta: una página web maliciosa aún puede intentar acceder a los puertos locales. Por eso LMSP combina varias medidas.

- Un servicio **DEBE** enlazarse por defecto a las direcciones loopback. **NO DEBE** escuchar en `0.0.0.0` ni en ninguna otra dirección que no sea loopback, salvo que el modo LAN esté activado ([sección 10.5](https://madeforagent.com/es/lmsp/1.0/security.md#lan)).
- En la primera ejecución, un servicio **DEBERÍA** generar un secreto de servicio aleatorio de alta entropía y usarlo, en lugar de cualquier valor por defecto incorporado, para emitir y verificar tokens.
- Toda solicitud a la interfaz principal **DEBE** llevar un token de portador válido, salvo los endpoints de arranque enumerados en la [sección 4.2](https://madeforagent.com/es/lmsp/1.0/endpoints.md#conventions). Provenir de loopback nunca basta por sí solo.

## 10.2 Emparejamiento y tokens {#pairing}

Un cliente obtiene su propio token de portador con un código de emparejamiento local. El usuario pide al servicio que muestre un código de emparejamiento, del modo que el servicio ofrezca, y el cliente lo envía:

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

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

| Campo de la solicitud | Significado |
| --- | --- |
| `client_name` | Nombre para mostrar del cliente, que se muestra al usuario. |
| `pairing_code` | El código que el usuario obtuvo del servicio. |
| `scopes` | Lista opcional de ámbitos solicitados. Por defecto es `["inference"]`. |

El servicio responde con un token. El `token_type` es siempre `Bearer`:

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

Después, el cliente envía `Authorization: Bearer <token>` con cada solicitud.

- Un código de emparejamiento **DEBE** ser de un solo uso y **DEBERÍA** caducar en un plazo de 5 minutos. **DEBERÍA** tener al menos 40 bits de entropía. Un servicio **DEBE** limitar la frecuencia de los intentos fallidos. Un código incorrecto o caducado se responde con `401` y `unauthorized`.
- Los tokens son independientes para cada cliente, de modo que el usuario puede revocar uno sin afectar a los demás. Un servicio **DEBERÍA** permitir al usuario listar y revocar los clientes emparejados.
- Un cliente **DEBERÍA** guardar su token en el llavero o en el administrador de credenciales del sistema operativo. Un servicio **DEBERÍA** almacenar solo un hash de cada token.
- Un token ausente, no válido o revocado se responde con `401`, `unauthorized` y una cabecera `WWW-Authenticate: Bearer`. Un token válido que carece del ámbito que necesita un endpoint se responde con `403` y `forbidden`.

## 10.3 Ámbitos {#scopes}

Los permisos se dividen en ámbitos distintos. Descargar modelos, eliminar modelos y ejecutar herramientas nunca viajan con el ámbito de inferencia.

| Ámbito | Permite |
| --- | --- |
| `inference` | Leer el catálogo de modelos, crear respuestas y tareas, y leer y cancelar las tareas del propio cliente. |
| `models:manage` | Cargar y liberar modelos de la memoria. |
| `models:install` | Reservado. Descargar y eliminar modelos. |
| `tools:execute` | Reservado. Ejecutar herramientas en el lado del servicio. |

Las tareas y las respuestas almacenadas pertenecen al cliente que las creó. Un servicio **DEBERÍA** responder a la solicitud de otro cliente como si no existieran (`task_not_found` o `response_not_found`).

## 10.4 Protecciones del navegador y de la red {#browser}

- Un servicio **DEBE** rechazar por defecto las solicitudes de navegador de origen cruzado, y permitir solo los valores de `Origin` configurados explícitamente. Una solicitud con cualquier otro `Origin` se responde con `403` y `forbidden`.
- Cuando se permite un origen, el servicio responde a sus solicitudes previas CORS y envía `Access-Control-Allow-Origin` con ese origen exacto, nunca con `*`.
- Un servicio **DEBE** validar la cabecera `Host`, para evitar el DNS rebinding. Solo acepta los nombres de host que sirve: los nombres y direcciones loopback, más los nombres configurados para el modo LAN. Cualquier otro valor se responde con `403` y `forbidden`.

## 10.5 Modo LAN {#lan}

El modo LAN significa escuchar más allá de las direcciones loopback.

- Un servicio **NO DEBE** activar el modo LAN salvo que el usuario lo habilite explícitamente.
- En modo LAN, un servicio **DEBE** exigir autenticación y **DEBERÍA** activar también TLS. Un cliente **NO DEBERÍA** enviar un token por HTTP sin cifrar a una dirección que no sea loopback, salvo que el usuario lo permita explícitamente.
- El anuncio mDNS solo se permite en modo LAN, cuando el usuario ha activado además el descubrimiento en la LAN ([sección 3.2](https://madeforagent.com/es/lmsp/1.0/discovery.md#mdns)).

## 10.6 Registro y privacidad {#logging}

- Las rutas de modelos, los registros, los prompts y el contenido generado **NO DEBEN** aparecer en los anuncios mDNS.
- Por defecto, un servicio **DEBERÍA** registrar solo metadatos (horas, endpoints, códigos de estado, ids, recuentos de tokens y duraciones). **NO DEBERÍA** registrar prompts completos ni contenido generado.
- Las respuestas de estado y los detalles de error **NO DEBEN** contener rutas de modelos, prompts, tokens de acceso ni otra información sensible.
