Volver a la wiki

Fondos de plano compartidos entre organizaciones y borrado a ciegas (task #252)

Cuándo

Reparado el 2026-08-23 en el commit 5936c9b4 (PR #422, v1.82.4, task #252). La fecha de introducción del bug no está registrada: lleva presente desde que existe la subida de fondos de plano en blueprints/api/blueprints.py, sin fecha exacta conocida — se descubrió al auditar el disco de producción en la ronda del 23-08-2026.

Síntomas visibles

Causa raíz

Tres huecos independientes en el ciclo de vida del fondo de un Blueprint:

  1. Sin namespacing por organización: update_blueprint_bg guardaba el fondo en una carpeta plana (uploads/blueprints/) con el nombre de fichero que trajera el navegador del usuario, saneado pero sin prefijo de organización — nombres repetidos entre tenants colisionaban.
  2. Borrado ciego al reemplazar: al subir un fondo nuevo, el código borraba el fondo anterior (os.remove(old_path)) sin comprobar si algún otro Blueprint —de la misma organización o de otra, vía restore de backup— seguía apuntando a ese mismo fichero.
  3. Nadie liberaba el fichero al final del ciclo de vida: ni el borrado definitivo de un plano (permanent_delete_blueprint, empty_blueprint_trash) ni el fallo de un import de Auto-Plan (que escribe la imagen en disco ANTES de encolar el análisis) borraban el fondo huérfano resultante.

Con RLS (Row Level Security) activo a nivel de base de datos, el aislamiento entre organizaciones estaba garantizado en las filas de la tabla blueprints_blueprint — pero el filesystem no tiene RLS: un os.remove sobre una ruta compartida es una fuga de aislamiento tan real como una consulta sin filtro de organización, y aquí no había ninguna barrera que lo impidiera.

Fix aplicado

Commit 5936c9b4b0218776753940703e8749e98ed1450b (PR #422):

Lecciones

Preventivos futuros

Véase también

Subir