Auditoría Suprema 2 · Tanda 1 (monitoring + racks): gates de permiso en Observatory, CNS y radar de integridad
Cuándo
31-08-2026 · commit 29f793c (PR #477, v1.91.0). Segundo PR de la Tanda 1 de la Auditoría Suprema 2 — el primero (v1.90.0, mismo día) cerró 4 ALTA equivalentes en el dominio core. Esta entrega cubre monitoring y racks.
Síntomas visibles
Tres endpoints/grupos de endpoints comprobaban solo que el usuario pertenecía a la organización (get_current_org), nunca su nivel de permiso dentro de ella:
- Observatory (
monitoring/api/observatory.py) — 7 endpoints sinrequire_perm: el layout del panel, las notas rápidas y los ajustes de gráficas son preferencias de toda la organización (no personales), y se leían/sobrescribían sin comprobar el scopeobservatory. Un usuario conobservatory: nonepodía tocarlas igual que un admin. - API CNS (
monitoring/api/insight_execution.py,insights.py,insight_conversations.py,tutor.py) — ningúnrequire_perm. El vector más grave: un usuarioreadonly(que sí tienecns:view) podía ejecutar en los equipos los comandos SSH que la IA propone, víaPOST /apply, sin tenercns:edit. - Radar de integridad (
racks/api/integrity.py, endpointoverview) — servía inventario de red (IP, hostname, vendor, número de serie, MAC) exigiendo solo pertenencia a la org, sin comprobarnetwork:view— a diferencia de su endpoint hermanocable-report, que sí lo exige.
Causa raíz
Mismo patrón sistémico ya visto en el core (v1.90.0, mismo día) y en la Auditoría Suprema original sobre network y racks: el endpoint valida la organización pero no el nivel de permiso (ModulePermission) del usuario dentro de ella. No es un fallo puntual — es una clase de vulnerabilidad que reaparece dominio a dominio conforme se van auditando, porque require_perm no es un middleware automático: hay que declararlo explícitamente en cada endpoint Ninja.
Fix aplicado
Commit 29f793c13679323ee24c1e267d5b426c7f8ca1bc (PR #477):
require_perm(request, "observatory", "view"|"edit")en los 7 endpoints de Observatory —viewen lecturas,editen escrituras — antes derequire_org.require_perm(request, "cns", "edit")enapply/dry_run/rollback/acknowledge/revise/tutor-clear;"view"en list/stats/detail/conversations/tutor. Los endpoints de ingesta del Agente (receive_insight,report_recovery,receive_execution_result,explain) quedan fuera del gate a propósito: se autentican por el JWT del Agente, no por sesión de usuario.purgeya era superuser-only antes del fix.require_perm(request, "racks", "view")yrequire_perm(request, "network", "view")enintegrity.overview— igual que su endpoint hermanocable-report.- 13 tests nuevos:
tests/monitoring/test_cns_observatory_authz.py(100 líneas) ytests/racks/test_integrity_authz.py(42 líneas) — cubren que unreadonlyno ejecuta insights ni sobrescribe el observatory, quecns:none/network:none/observatory:nonereciben 403, y que los caminos legítimos (view) siguen devolviendo 200.
Lecciones
El mismo patrón — “gate por organización, nunca por nivel” — ha aparecido ya en core, network (Suprema 1, SA1-SA5), racks (Suprema 1) y ahora monitoring. Cada auditoría nueva lo vuelve a encontrar en un dominio distinto porque no hay ningún control estructural que obligue a declarar require_perm en un endpoint Ninja — depende de que la auditoría manual llegue a ese archivo.
Preventivos futuros
- Continuar la Tanda 1 de la Auditoría Suprema 2 sobre los dominios que falten.
- Valorar un check de CI (lint/test estructural) que detecte endpoints Ninja mutantes sin
require_perm, para no depender solo de rondas de auditoría sucesivas.
Véase también
- [[entity—core—service—require-perm]]
- [[entity—core—service—has-permission]]
- [[crearack—conceptos—usuarios-y-permisos]]
- [[incident—20260602—auditoria-suprema-mini-tanda-seguridad]]
- [[incident—20260602—auditoria-suprema-racks]]
- [[feature—monitoring—auditoria-suprema-sa6-observatory-realtime]]
- [[feature—monitoring—auditoria-suprema-sa3-cns-insights-ia]]