Reports
BAJA[DENEGACIÓN DE SERVICIO]#3508852

Nextcloud Tables: un iconName inexistente rompe la interfaz de una aplicación y deja sus datos inaccesibles

La API de contextos de Nextcloud Tables aceptaba cualquier valor en iconName. Un icono inexistente hacía fallar el frontend al pintar la aplicación, que dejaba de mostrarse con todas sus tablas para todos los usuarios.

Resumen
Resumen en castellano de un reporte público, no una traducción literal. El código y los comandos se mantienen como en el original.

Resumen

En Nextcloud Tables, las "Applications" (internamente, contexts) agrupan tablas y vistas bajo un nombre y un icono. El icono se guarda como texto en el parámetro iconName del endpoint PUT /ocs/v2.php/apps/tables/api/2/contexts/<id>, y el backend lo almacenaba sin comprobar que correspondiera a un icono real.

El problema aparecía después, en el navegador: cuando el frontend intentaba pintar una aplicación cuyo icono no podía resolver, fallaba por completo. La tarjeta de la aplicación no cargaba y, con ella, desaparecían de la vista las tablas, los registros y la configuración que contenía. Los datos seguían en el servidor, pero nadie podía llegar a ellos desde la interfaz.

Bastaba con tener permiso de edición sobre la aplicación. El investigador lo clasificó como CWE-20 (validación de entrada incorrecta) y CWE-755 (manejo incorrecto de condiciones excepcionales). El reporte figura con severidad baja, Nextcloud lo dio por resuelto y pagó una recompensa de importe no público. Se envió el 13 de enero de 2026 y se hizo público el 20 de octubre de 2026.

Pasos de reproducción

  1. Iniciar sesión en Nextcloud con un usuario que tenga permiso de edición sobre una aplicación de Tables (en el ejemplo, el contexto con ID 8).
  2. Editar la aplicación y mandar la petición de actualización con un iconName que no exista:
PUT /ocs/v2.php/apps/tables/api/2/contexts/8 HTTP/1.1
Host: 127.0.0.1:8080
Content-Type: application/json
X-Requested-With: XMLHttpRequest
Origin: http://127.0.0.1:8080

{"name":"pops","iconName":"asdsadasd","description":"","nodes":[{"id":17,"type":0,"permissions":7}]}
  1. Comprobar que el servidor contesta 200 OK: el valor inválido queda guardado.
  2. Recargar la interfaz de Tables. La aplicación ya no se muestra, su contenido no aparece y la interfaz queda rota, sin ningún mensaje de error que explique el motivo.

Impacto

Cualquier usuario con permiso de edición sobre una aplicación podía dejarla inutilizable para todos los demás con una sola petición. El efecto se mantiene en el tiempo, porque el valor queda guardado en el servidor y el fallo se repite en cada carga:

  • Nadie puede ver desde la interfaz las tablas, los registros ni la configuración de esa aplicación.
  • Como no aparece ningún error, quien la usa puede pensar que los datos se han borrado, aunque siguen almacenados.

El investigador lo plantea como un sabotaje interno: un empleado con permiso de edición sobre una aplicación con datos financieros, de recursos humanos o de incidentes podría bloquear el trabajo del resto y hacer creer que se ha perdido información. Los datos no se pierden realmente: siguen en el servidor, solo que inaccesibles desde la interfaz.

Remediación

El reporte no detalla qué cambio aplicó Nextcloud, solo que el fallo quedó resuelto. El investigador propuso dos medidas complementarias:

  • En el backend, comprobar iconName contra la lista fija de iconos permitidos y responder 400 Bad Request a cualquier otro valor.
  • En el frontend, usar un icono por defecto cuando no se pueda cargar el indicado, en lugar de dejar de pintar la aplicación.

Qué aprender de este caso

  • Los campos "decorativos" que el frontend convierte en un recurso (nombres de icono, colores, temas, plantillas) merecen la misma atención que los datos: prueba a guardar valores que no existen a través de la API y recarga la interfaz para ver si algo deja de pintarse.
  • Si un campo solo admite un catálogo cerrado, como los iconos de Tables, valídalo en el servidor contra esa lista y rechaza lo demás; que el selector de la interfaz solo ofrezca opciones válidas no impide mandar otra cosa directamente a /contexts/<id>.
  • En el frontend, un dato auxiliar que falla no debería tumbar el componente entero: un icono que no se resuelve tiene que caer en uno por defecto, no impedir que se muestre el contenido.
  • Cuando un usuario con permisos limitados puede guardar algo que otros van a cargar, piensa en el daño persistente que causa a esos otros: aquí bastaba editar el icono para dejar sin acceso a la aplicación a todos los que la usaban.