Incidentedraftcreado Thu Sep 24#core#security#rbac#permissions#django#python#audit-trail#mega-auditoria-t02
Cuándo
24-09-2026, PR #592, commit 59be81cd. Segunda tanda (T02) de la mega-auditoría del 24-09-2026 sobre gestión de usuarios; publicada como v1.154.0.
Síntomas visibles
Ningún incidente reportado por clientes — son hallazgos de auditoría interna. Seis huecos de seguridad en la superficie de gestión de usuarios (API Ninja + vistas HTMX):
- El alta HTMX (
POST /htmx/users/create) guardaba el rol tal cual llegaba del formulario, sin validarlo contraVALID_ROLESni contra el nivel de quien lo creaba (B-05, D1-01). - Dos rutas HTMX de edición (
GET /htmx/users/<id>/edit,PUT /htmx/users/<id>) seguían vivas sin que ninguna plantilla ni JS las llamara, y dejaban cambiar rol/contraseña de cualquier usuario de la organización, superusuarios incluidos (D1-02). - La única protección contra tocar a alguien “por encima” comprobaba
is_superuser/is_staff, pero no el nivel de permisos por módulo: un operador con overrideusers:adminpodía resetear la contraseña de unadminnormal y entrar como él (B-28). - Crear, editar, borrar un usuario o quitarle el MFA no dejaba ningún rastro en el registro del sistema (B-32).
- Varias vistas HTMX de solo lectura (listado/búsqueda de racks, nombre inline, mapas, papelera de racks/mapas/dispositivos, grupos) solo exigían sesión iniciada, no el permiso de ver ese módulo (B-63).
Causa raíz
Las reglas de “quién puede tocar a quién” vivían duplicadas: la API Ninja las tenía a medias (sin comparar niveles de permiso) y las vistas HTMX reimplementaban su propia copia, más vieja y más floja. Las rutas de edición HTMX quedaron huérfanas tras mover ese flujo al modal de base.html (que ya llama a la API), pero nadie las borró. Ninguna de las dos capas escribía en el registro de auditoría para acciones sobre usuarios.
Fix aplicado (commit 59be81cd, PR #592)
- Nueva función única
target_outranks_actor(actor, target)encore/api/users.py: compara el nivel efectivo de permisos de target contra el de actor en cada scope (además del caso superuser/staff) y bloquea si el objetivo está por encima en cualquiera. La usan tanto la API (update_user,delete_user,delete_user_mfa_device) como las vistas HTMX, vía el helper_deny_target. POST /htmx/users/createvalida ahorarole in VALID_ROLESy_role_exceeds_grantor, igual quePOST /api/users/.- Retiradas
user_edit_formyuser_updatedecore/htmx_views.py, sus rutas encore/htmx_urls.pyy la plantillatemplates/htmx/users/edit_form.html. log_action(categoríaAUTH) enuser.create,user.update,user.delete,user.mfa_removeyuser.mfa_remove_all, por API y por HTMX, sin registrar la contraseña (solo que cambió).- Gate
has_permission(request.user, <scope>, "view")añadido a las vistas HTMX de solo lectura de racks, mapas, papelera y grupos. - Cobertura:
tests/api/test_mega_t02.py(255 líneas nuevas).
Lecciones
- Una regla de “quién manda sobre quién” que vive en dos sitios (API y HTMX) tiende a divergir: la copia más vieja se queda sin el refinamiento que recibe la otra. Unificarla en una función que llaman ambas capas es lo que impide que reaparezca.
- Una ruta sin llamador conocido no es inofensiva: mientras exista, sigue expuesta. D1-02 solo salió a la luz auditando, no por un fallo reportado.
Preventivos futuros
- Al mover un flujo de HTMX a la API (o viceversa), borrar la ruta vieja en el mismo cambio, no dejarla “por si acaso”.
- Toda acción que cambie o borre un usuario (o le quite un factor de MFA) pasa por
log_action; si se añade un mutador nuevo sobreUser, este es el patrón a copiar. - Límite honesto: el rastro va en la categoría
AUTHporque una categoríaUSERSdedicada exigiría migración; fuera de alcance de esta tanda. El logo y los datos de empresa (core/api/settings.py) tampoco dejan rastro todavía.
Véase también
- [[entity—core—service—has-permission]]
- [[entity—core—service—log-action]]
- [[decision—20260607—audit-logs-best-effort]]
- [[feature—security—auditoria-suprema-2-tanda-1-core]]
- [[incident—20260602—auditoria-suprema-mini-tanda-seguridad]]
- [[crearack—conceptos—usuarios-y-permisos]]
- [[crearack—settings—user-management]]
Referenciado desde
- Mega-auditoría B-16 (27-09-2026): un Agente secundario recibía las credenciales SNMP de todos los equipos
- Mega-auditoría, ronda 6 (25-09-2026): siete brechas cerradas en control de acceso, sesión y CSRF
- vmauth con usuario y contraseña delante de VictoriaMetrics y Alertmanager en NetBird (mega-auditoría B-45)