Reports
MEDIA[IDOR / BOLA]#3689633

Discourse: un editor de etiquetas podía modificar etiquetas ocultas usando su ID en las rutas de sinónimos

Los endpoints de sinónimos y de ajustes de etiquetas de Discourse solo comprobaban permisos sobre la etiqueta visible, así que un editor sin acceso podía convertir etiquetas ocultas en sinónimos indicando su ID numérico.

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 Discourse, para editar una etiqueta un usuario necesita dos cosas: permiso general de edición de etiquetas y poder ver esa etiqueta concreta. Las etiquetas ocultas o restringidas, que pertenecen a grupos de etiquetas a los que el usuario no tiene acceso, deberían quedar fuera de su alcance.

El fallo es una referencia directa insegura a objetos (IDOR) en las rutas que gestionan sinónimos por ID. Había dos puntos afectados:

  • TagsController#create_synonyms: solo autorizaba la etiqueta de destino con guardian.ensure_can_edit_tag!(@tag). Después pasaba los IDs de sinónimos enviados por el usuario a DiscourseTagging.add_or_create_synonyms sin comprobar si podía ver o editar cada una de esas etiquetas.
  • TagSettingsUpdater: aceptaba IDs en new_synonyms y removed_synonym_ids y cambiaba las relaciones de sinónimos sin revisar los permisos de cada etiqueta.

Es decir, la comprobación de permisos se hacía sobre la etiqueta visible, pero no sobre las etiquetas que realmente se modificaban. El investigador lo reprodujo en local con el código de la versión 2026.4.0-latest. También señaló que, si el equipo de Discourse ya había corregido un problema parecido con sinónimos de etiquetas ocultas, este caso sería una variante o una corrección incompleta.

Pasos de reproducción

Preparación:

  1. Crea un usuario sin rol de administrador que pertenezca a edit_tags_allowed_groups.
  2. Crea una etiqueta visible que ese usuario pueda editar.
  3. Crea una etiqueta oculta o restringida dentro de un grupo de etiquetas al que el usuario no tenga acceso.
  4. Inicia sesión con el usuario editor.

Comprobar que la etiqueta oculta no es visible:

  1. Solicita la información de la etiqueta oculta:
GET /tag/<hidden_tag_id>/info.json
  1. La respuesta es un 404, así que el usuario no puede ver esa etiqueta.

Primera vía, el endpoint de sinónimos:

  1. Envía la petición indicando como sinónimo el ID numérico de la etiqueta oculta:
POST /tag/<visible_tag_id>/synonyms.json

tags[0][id]=<hidden_tag_id>
  1. La petición funciona y la etiqueta oculta pasa a ser sinónimo de la visible.

Segunda vía, el endpoint de ajustes:

  1. Restablece el estado inicial y envía:
PUT /tag/<visible_tag_id>/settings.json

tag_settings[new_synonyms][0][id]=<hidden_tag_id>
  1. Esta petición también funciona y cambia la relación de sinónimo de la etiqueta oculta.

En los dos casos se actualiza el campo target_tag_id de la etiqueta oculta. El resultado de las pruebas que acompañan al reporte fue:

2 examples, 0 failures

Impacto

Un usuario con permiso para editar etiquetas, pero sin rol de administrador, podía cambiar etiquetas ocultas o restringidas que no puede ver ni editar, simplemente indicando su ID numérico. En concreto, podía:

  • Convertir una etiqueta oculta en sinónimo de una etiqueta visible que controla, cambiando su target_tag_id.
  • Alterar relaciones de sinónimos de etiquetas restringidas mediante new_synonyms y removed_synonym_ids en los ajustes.

Como resultado, un usuario sin autorización podía modificar la clasificación de las etiquetas ocultas y estropear la integridad de las relaciones entre etiquetas.