CreaRack-SL

Decisión: Activar enforcement del Bearer local del Agent (Raíz 3 cerrada)

Resumen

Fecha: 2026-06-11 (Sesión 129)
Cierre: Raíz 3 de la Auditoría Suprema (dominio terminal del Agent local)
Versión Agent: 2.1.1 → 2.1.2
Status: ✅ Implementado y verificado E2E

El enforcement del Bearer local (AGENT_LOCAL_AUTH_ENFORCE) pasa de OFF (default en 2.1.1, por prudencia) a ON (default en 2.1.2, tras verificación completa del circuito E2E).

Contexto: por qué decidimos esperar en 2.1.1

La Fase 3 de auth local del Agent requería que:

  1. El Agent deposite su token en el SaaS (servidor CreaRack) durante el registro/vinculación.
  2. El frontend (navegador del tenant) solicite ese token vía GET /api/agent/local-token (sesión autenticada + permiso fleet:view).
  3. El frontend inyecte el token como Bearer en llamadas HTTP locales al Agent (puerto 5050).
  4. El Agent valide ese Bearer antes de procesar comandos.

En 2.1.1 (s128), activamos (1) pero dejamos (4) opcional — el Agent aceptaba llamadas sin Bearer. Razón: detectamos un bug en el interceptor del frontend (agente_auth.js) que hacía fallar el paso (2). Si hubiera sido obligatorio, se habría bloqueado todo en cascada.

Decisión en 2.1.2

Tras verificar E2E que el circuito funciona:

  • ✅ El Agent deposita el token durante connector._register_local_token().
  • ✅ El SaaS lo custodia y lo entrega solo a la sesión del tenant propietario.
  • ✅ El frontend lo recupera sin errores (bug del interceptor corregido).
  • ✅ El Agent lo valida y acepta llamadas legítimas.
  • ✅ Se rechaza acceso desde JavaScript malicioso en el navegador (sin token válido).

Consecuencia: activamos AGENT_LOCAL_AUTH_ENFORCE=1 por defecto. Los 12 riesgos ALTA de la Raíz 3 se cierran:

RiesgoMitigación
DNS-rebinding (navegador abre http://127.0.0.1:5050)Exige Bearer válido del SaaS.
CSRF (formulario en web ajena + navegador con sesión del tenant)Exige Bearer en cada petición (CSRF no lo roba).
Navegador malicioso ejecutando comandos localesSin Bearer de la sesión legítima, rechazado.

Escape hatch (marcha atrás sin recompilar)

Si un cliente experimentara un problema con el circuito:

AGENT_LOCAL_AUTH_ENFORCE=0

Desactiva la exigencia del Bearer sin perder el depósito del token. El Agent sigue custodiándolo, pero no lo valida (postura defensiva temporal, p.ej. durante troubleshooting).

Cambios técnicos

terminal/agent/core/local_token.py

# Antes (2.1.1):
LOCAL_AUTH_ENFORCE = os.environ.get("AGENT_LOCAL_AUTH_ENFORCE", "").strip().lower() in ("1", "true", "yes", "on")
# Default: OFF (False)

# Ahora (2.1.2):
LOCAL_AUTH_ENFORCE = os.environ.get("AGENT_LOCAL_AUTH_ENFORCE", "1").strip().lower() not in ("0", "false", "no", "off")
# Default: ON (True) — escape con "=0"

static/js/modules/agent_auth.js (bug fix)

// Antes (2.1.1):
const agentId = (info.saas_info && info.saas_info.agent_id) || info.agent_id;
// info.saas_info era undefined → agentId = undefined → token = null → 401 con enforcement ON

// Ahora (2.1.2):
const agentId = (info.saas && info.saas.agent_id) || info.agent_id;
// Léxicamente, /info expone el agent_id bajo la clave `saas` (health.py _get_debug_info)

Verificación pre-deployment

  • ✅ 7 tests verdes en tests/agent/test_agent_local_auth.py:
    • test_auth_required_on_by_default(): verifica que el flag está ON.
    • test_auth_required_escape_hatch(): verifica que =0 lo desactiva.
  • ✅ Ruff linting: sin errores.
  • ✅ E2E en Docker: status 200 + token entregado correctamente.

Impacto operacional

Para los clientes:

  • El Agent sigue funcionando si ya tiene un token depositado (caso normal).
  • Si hay problemas, AGENT_LOCAL_AUTH_ENFORCE=0 es la marcha atrás (sin recompilar).
  • El SaaS debe haber desplegado la corrección del interceptor antes de publicar el Agent 2.1.2.

Para el equipo de Edu (build + release):

  1. Esperar a que crearack.com despliegue (agent_auth.js corregido).
  2. Ejecutar build_agent.bat (genera 2.1.2).
  3. Smoke tests: dashboard + consola SSH + discovery.
  4. Publicar agent-v2.1.2, borrar versión anterior.

Cierre de auditoría

Raíz 3 (dominio terminal del Agent local) pasa de ABIERTA a CERRADA:

  • ✅ 12 ALTA (DNS-rebinding, CSRF, navegador malicioso) → mitigados.
  • ✅ Circuito E2E verificado.
  • ✅ Tests + linting + E2E + escape hatch documentados.

Véase también

  • [[concept—saas—multi-tenancy]]
  • [[entity—terminal—service—agente-auth-local]]
  • [[runbook—agent—bearer-token-troubleshooting]]
  • [[incident—20260610—agent-2-1-1-interceptor-bug]]
  • [[concept—security—dns-rebinding-csrf]]