Volver a la wiki

Full Backup: Scoping de uploads por organización (fix security)

Resumen

El Full Backup (backup_full() + generate_backup()) empaquetaba toda la carpeta uploads/, lo que incluía uploads de todas las organizaciones (porque se guardan por tipo, sin prefijo de org). Resultado: (1) ZIP inflado (30-40 MB → 333 MB) + (2) fuga cross-tenant (cualquier admin se descargaba ficheros de otras empresas).

Fix: Nuevos helpers collect_org_upload_files() + org_upload_image_paths() en backup_service.py que empaquetan solo los ficheros referenciados por los registros de la org (stencils + blueprints), con normalización de rutas, dedup y guard anti-path-escape.

Problema detectado (s104 · Auditoría Etapa 3)

Solución

Helpers en core/services/backup_service.py

_media_relpath(image_path)

collect_org_upload_files(image_paths)

org_upload_image_paths(backup_data)

Cambios en endpoints + servicios

racks/api/export/backup.py::backup_full(request)

core/services/backup_service.py::generate_backup(org)

Tests

tests/api/test_backup.py — 5 nuevos tests:

  1. TestMediaRelpathHelper::test_normalizes_variants — _media_relpath() convierte /static/uploads/... ↔ /media/uploads/... ↔ uploads/... a forma canónica
  2. TestMediaRelpathHelper::test_rejects_non_uploads_and_empty — rechaza paths vacíos, no-uploads, etc.
  3. TestCollectOrgUploadFiles::test_only_existing_uploads_files — solo empaqueta ficheros que existen en disco
  4. TestCollectOrgUploadFiles::test_dedupes_and_blocks_path_escape — dedup + bloquea intento de ../../../etc/passwd
  5. TestBackupTenantScoping::test_backup_excludes_other_org_uploads — ⭐ generate_backup(orgA) excluye los uploads de orgB (cierre de fuga)

Suite de API: 258 verde (1 skip preexistente). Sin migraciones.

Verificación

Véase también

Subir