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 conguardian.ensure_can_edit_tag!(@tag). Después pasaba los IDs de sinónimos enviados por el usuario aDiscourseTagging.add_or_create_synonymssin comprobar si podía ver o editar cada una de esas etiquetas.TagSettingsUpdater: aceptaba IDs ennew_synonymsyremoved_synonym_idsy 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:
- Crea un usuario sin rol de administrador que pertenezca a
edit_tags_allowed_groups. - Crea una etiqueta visible que ese usuario pueda editar.
- Crea una etiqueta oculta o restringida dentro de un grupo de etiquetas al que el usuario no tenga acceso.
- Inicia sesión con el usuario editor.
Comprobar que la etiqueta oculta no es visible:
- Solicita la información de la etiqueta oculta:
GET /tag/<hidden_tag_id>/info.json
- La respuesta es un 404, así que el usuario no puede ver esa etiqueta.
Primera vía, el endpoint de sinónimos:
- 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>
- La petición funciona y la etiqueta oculta pasa a ser sinónimo de la visible.
Segunda vía, el endpoint de ajustes:
- Restablece el estado inicial y envía:
PUT /tag/<visible_tag_id>/settings.json
tag_settings[new_synonyms][0][id]=<hidden_tag_id>
- 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_synonymsyremoved_synonym_idsen 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.