8 min

Subidas de archivos seguras: permisos, límites, URLs firmadas y escaneos

Las subidas de archivos seguras en apps web requieren permisos estrictos, límites de tamaño, URLs firmadas y patrones sencillos de escaneo para evitar incidentes.

Subidas de archivos seguras: permisos, límites, URLs firmadas y escaneos

Por qué las subidas de archivos son riesgosas (en lenguaje sencillo)

Las subidas de archivos parecen inofensivas: una foto de perfil, un PDF, una hoja de cálculo. Pero a menudo son el primer incidente de seguridad porque permiten que extraños envíen a tu sistema una caja misteriosa. Si la aceptas, la almacenas y se la muestras a otras personas, has creado una nueva vía para atacar tu app.

El riesgo no es solo “alguien sube un virus”. Una subida maliciosa puede filtrar archivos privados, disparar tu factura de almacenamiento o engañar a usuarios para que entreguen acceso. Un archivo llamado “invoice.pdf” puede no ser un PDF en absoluto. Incluso PDFs e imágenes legítimas pueden causar problemas si tu app confía en metadatos, genera vistas previas automáticamente o los sirve con reglas equivocadas.

Los fallos reales suelen verse así:

  • Alguien adivina una URL de archivo y descarga el documento de otro usuario.
  • Un archivo HTML subido se sirve como página web y muestra un aviso que roba credenciales.
  • Un atacante sube archivos enormes repetidamente hasta que tu app se ralentiza o se cae.
  • Se falsifica un tipo de archivo “seguro” y luego el personal lo abre en una máquina interna.

Un detalle impulsa muchos incidentes: almacenar archivos no es lo mismo que servirlos. El almacenamiento es donde guardas los bytes. Servir es cómo esos bytes se entregan a navegadores y apps. Las cosas se complican cuando una app sirve subidas de usuarios con el mismo nivel de confianza y reglas que el sitio principal, de modo que el navegador trata la subida como “confiable”.

“Lo suficientemente seguro” para una app pequeña o en crecimiento suele significar que puedas responder cuatro preguntas sin evasivas: quién puede subir, qué aceptas, cuánto y con qué frecuencia, y quién puede leerlo después. Incluso si construyes rápido (con código generado o una plataforma guiada por chat), esos límites siguen importando.

Un modelo de amenazas simple para subidas

Trata cada subida como entrada no confiable. La forma práctica de mantener las subidas seguras es imaginar quién podría abusar de ellas y qué significa “éxito” para ese atacante.

La mayoría de los atacantes son bots que buscan formularios de subida débiles o usuarios reales que empujan límites para obtener almacenamiento gratis, rascar datos o trolear el servicio. A veces también es un competidor que prueba fugas o caídas.

¿Qué buscan? Normalmente uno de estos resultados:

  • Ejecutar código en tus servidores subiendo algo que se ejecute.
  • Robar archivos privados adivinando, reutilizando o compartiendo URLs de descarga.
  • Dañar la disponibilidad inundando con subidas o forzando procesamiento caro.
  • Inflar tu factura mediante crecimiento de almacenamiento o descargas pesadas.

Luego mapea los puntos débiles. El endpoint de subida es la puerta principal (archivos sobredimensionados, formatos extraños, tasas altas de petición). El almacenamiento es la trastienda (buckets públicos, permisos incorrectos, carpetas compartidas). Las URLs de descarga son la salida (predecibles, de larga vida o no ligadas a un usuario).

Ejemplo: una funcionalidad de “subir curriculum”. Un bot sube miles de PDFs grandes para subir costos, mientras que un usuario abusivo sube un archivo HTML y lo comparte como “documento” para engañar a otros.

Antes de añadir controles, decide qué importa más para tu app: privacidad (quién puede leer), disponibilidad (puedes seguir sirviendo), coste (almacenamiento y ancho de banda) y cumplimiento (dónde se guarda y cuánto tiempo). Esa lista de prioridades mantiene las decisiones coherentes.

Permisos y control de acceso que realmente aguanten

La mayoría de los incidentes con subidas no son ataques sofisticados. Son errores simples de “puedo ver el archivo de otra persona”. Trata los permisos como parte de las subidas, no como una característica añadida después.

Comienza con una regla: denegar por defecto. Asume que cada objeto subido es privado hasta que permitas explícitamente el acceso. “Privado por defecto” es una buena base para facturas, archivos médicos, documentos de cuenta y cualquier cosa ligada a un usuario. Haz públicos los archivos solo cuando el usuario lo espere claramente (como un avatar público), y aun así considera acceso con tiempo limitado.

Roles que concuerden con el trabajo real

Mantén los roles simples y separados. Una división común es:

  • Uploader: puede crear subidas para su propia cuenta
  • Viewer: puede descargar archivos que tiene permitido ver
  • Support: puede acceder a archivos solo con una concesión temporal y auditable
  • Admin: puede gestionar políticas, pero no debería leer todo automáticamente

No confíes en reglas a nivel de carpeta como “todo en /user-uploads/ está bien”. Comprueba la propiedad o el acceso del tenant en tiempo de lectura, para cada archivo. Eso te protege cuando alguien cambia de equipo, sale de la organización o un archivo se reasigna.

Un buen patrón de soporte es estrecho y temporal: otorga acceso a un archivo específico, regístralo y expíralo automáticamente.

Validar tipo de archivo sin confiar en el cliente

La mayoría de los ataques en subidas comienzan con un truco simple: un archivo que parece seguro por su nombre o el encabezado del navegador, pero en realidad es otra cosa. Trata todo lo que envía el cliente como no confiable.

Comienza con una lista blanca: decide los formatos exactos que aceptas (por ejemplo, .jpg, .png, .pdf) y rechaza todo lo demás. Evita “cualquier imagen” o “cualquier documento” a menos que realmente lo necesites.

No confíes en la extensión del nombre ni en el encabezado Content-Type del cliente. Ambos son fáciles de falsificar. Un archivo llamado invoice.pdf puede ser ejecutable, y Content-Type: image/png puede ser mentira.

Un enfoque más fuerte es inspeccionar los primeros bytes del archivo, a menudo llamados “magic bytes” o firma del archivo. Muchos formatos comunes tienen encabezados consistentes (como PNG y JPEG). Si el encabezado no coincide con lo permitido, recházalo.

Una configuración práctica de validación:

  • Lista blanca de extensiones aceptadas (lado servidor).
  • Detectar el tipo MIME en el servidor (no usar el encabezado del cliente).
  • Olfatear las magic bytes para los formatos que soportas.
  • Generar un nombre de almacenamiento aleatorio y guardar el nombre original como metadato.
  • Bloquear formatos riesgosos a menos que los necesites, especialmente HTML, SVG y contenido tipo script.

Renombrar importa más de lo que parece. Si almacenas nombres proporcionados por el usuario directamente, invites trucos de rutas, caracteres extraños y sobreescrituras accidentales. Usa un ID generado para el almacenamiento y guarda el nombre original solo para mostrar.

Para fotos de perfil, acepta solo JPEG y PNG, verifica encabezados y elimina metadatos si puedes. Para documentos, considera limitar a PDF y rechazar contenido activo. Si más adelante decides permitir SVG o HTML, trátalos como potencialmente ejecutables y aíslalos.

Límites de tamaño, rate limits y bases contra DoS

La mayoría de las caídas por subidas no son “trucos sofisticados”. Son archivos enormes, demasiadas peticiones o conexiones lentas que ocupan servidores hasta que la app parece caída. Trata cada byte como un coste.

Establece límites de tamaño que funcionen realmente

Elige un máximo por característica, no un número global. Un avatar no necesita el mismo límite que un documento fiscal o un video corto. Fija el límite más pequeño que siga pareciendo normal, y añade una ruta de “subida grande” separada solo cuando realmente la necesites.

Haz cumplir los límites en más de un lugar, porque los clientes pueden mentir: en la lógica de la app, en el servidor web o proxy reverso, con timeouts de subida y con rechazo temprano cuando el tamaño declarado es demasiado grande (antes de leer todo el cuerpo).

Ejemplo concreto: avatares limitados a 2 MB, PDFs hasta 20 MB, y todo lo mayor requiere un flujo distinto (como subida directa a object storage con una URL firmada).

Rate limits y controles de abuso

Hasta los archivos pequeños pueden convertirse en DoS si alguien los sube en bucle. Añade rate limits en endpoints de subida por usuario y por IP. Considera límites más estrictos para tráfico anónimo que para usuarios autenticados.

Las subidas reanudables ayudan a usuarios reales con redes malas, pero el token de sesión debe ser estricto: expiración corta, ligado al usuario y atado a un tamaño y destino específico. Si no, los endpoints de “resume” se convierten en un conducto gratuito hacia tu almacenamiento.

Cuando bloquees una subida, devuelve errores claros para el usuario (archivo demasiado grande, demasiadas peticiones) pero no reveles detalles internos (stack traces, nombres de buckets, detalles de proveedores).

Opciones seguras de almacenamiento y entrega

Deploy with less hassle
Go from chat to hosted app, then iterate on upload security in minutes.

Las subidas seguras no se tratan solo de lo que aceptas. También importan dónde va el archivo y cómo se lo devuelves después.

Mantén los bytes de subida fuera de tu base de datos principal. La mayoría de las apps solo necesitan metadatos en la BD (ID del propietario, nombre de archivo original, tipo detectado, tamaño, checksum, clave de almacenamiento, tiempo de creación). Guarda los bytes en object storage o un servicio de archivos hecho para blobs grandes.

Separa archivos públicos y privados a nivel de almacenamiento. Usa distintos buckets o contenedores con reglas diferentes. Los archivos públicos (como avatares públicos) pueden leerse sin login. Los archivos privados (contratos, facturas, documentos médicos) nunca deberían ser legibles públicamente, ni siquiera si alguien adivina la URL.

Evita servir archivos de usuario desde el mismo dominio que tu app cuando puedas. Si se cuela un archivo arriesgado (HTML, SVG con scripts o rarezas de sniffing MIME del navegador), alojarlo en tu dominio principal puede convertirse en una toma de cuenta. Un dominio de descarga dedicado (o dominio de almacenamiento) limita el radio de impacto.

En las descargas, fuerza cabeceras seguras. Establece un Content-Type predecible basado en lo que permites, no en lo que afirma el usuario. Para cualquier cosa que el navegador pueda interpretar, prefiere enviarlo como descarga.

Algunos valores por defecto que evitan sorpresas:

  • Usa Content-Disposition: attachment para documentos.
  • Usa un Content-Type seguro (o application/octet-stream).
  • Almacena y sirve con claves de objeto opacas (no nombres de usuario).
  • Registra las descargas de archivos privados.

La retención también es seguridad. Borra subidas abandonadas, elimina versiones antiguas tras reemplazos y establece límites temporales para archivos temporales. Menos datos almacenados significa menos que filtrar.

URLs firmadas: cuándo usarlas y cómo mantenerlas ajustadas

Las URLs firmadas (a menudo llamadas pre-signed URLs) son una forma común de permitir que usuarios suban o descarguen archivos sin hacer público tu bucket de almacenamiento y sin enviar cada byte por tu API. La URL lleva permiso temporal y luego expira.

Dos flujos comunes:

  • Subida directa a almacenamiento: tu app emite una URL firmada de corta duración y el navegador sube directamente al object storage.
  • Subida a través del servidor: el archivo llega primero a tu API y luego tu servidor lo almacena.

Directo a almacenamiento reduce la carga de la API, pero hace que las reglas de almacenamiento y las restricciones de la URL sean más importantes.

Cómo mantener las URLs firmadas ajustadas

Trata una URL firmada como una llave de un solo uso. Hazla específica y de corta duración.

  • Expira las URLs de escritura rápido (a menudo 1–5 minutos). Mantén las URLs de lectura en minutos, no días.
  • Ata la URL a la clave de objeto exacta que esperas (un objeto, no una carpeta).
  • Añade restricciones donde sea posible: tipo de contenido esperado, tamaño máximo, checksum.
  • Emite URLs solo después de comprobar permisos.
  • Registra quién pidió la URL y por qué (ID de usuario, clave de objeto, propósito, IP/agent).

Un patrón práctico es crear primero un registro de subida (estado: pending), luego emitir la URL firmada. Tras la subida, confirma que el objeto existe y coincide en tamaño y tipo esperado antes de marcarlo como listo.

Paso a paso: un flujo de subida seguro que puedes implementar

Add signed URLs quickly
Generate a direct-to-storage upload flow with short-lived permissions you control.

Un flujo seguro de subidas es sobre todo reglas claras y estado claro. Trata cada subida como no confiable hasta que las comprobaciones lo confirmen.

Escribe lo que permite cada funcionalidad. Una foto de perfil y un documento fiscal no deberían compartir los mismos tipos de archivo, límites de tamaño ni visibilidad.

Un flujo práctico (con estados reales)

  1. Define tipos permitidos y un límite de tamaño por funcionalidad (por ejemplo: fotos hasta 5 MB; PDFs hasta 20 MB). Hacer cumplir las mismas reglas en el backend.

  2. Crea un “registro de subida” antes de que lleguen los bytes. Guarda: propietario (usuario u organización), propósito (avatar, factura, adjunto), nombre de archivo original, tamaño máximo esperado y un estado como pending.

  3. Sube a una ubicación privada. No dejes que el cliente elija la ruta final.

  4. Valida otra vez en servidor: tamaño, magic bytes/tipo, lista blanca. Si pasa, cambia el estado a uploaded.

  5. Escanea en busca de malware y actualiza el estado a clean o quarantined. Si el escaneo es asíncrono, mantén el acceso bloqueado mientras esperas.

  6. Permite descarga, vista previa o procesamiento solo cuando el estado sea clean.

Pequeño ejemplo: para una foto de perfil, crea un registro ligado al usuario con propósito avatar, almacénala de forma privada, confirma que es realmente JPEG/PNG (no solo por el nombre), escanéala y luego genera una URL de vista previa.

Patrones básicos de escaneo de malware (sin prometer demasiado)

El escaneo de malware es una red de seguridad, no una promesa. Detecta archivos malos conocidos y trucos obvios, pero no lo detectará todo. El objetivo es simple: reducir riesgo y hacer que los archivos desconocidos sean inofensivos por defecto.

Un patrón fiable es cuarentena primero. Guarda cada nueva subida en una ubicación privada y márcala como pendiente. Solo después de que pase las comprobaciones la mueves a una ubicación “clean” (o la marcas como disponible).

Los escaneos síncronos funcionan solo para archivos pequeños y tráfico bajo porque el usuario espera. La mayoría de las apps escanean de forma asíncrona: aceptan la subida, devuelven un estado de “procesando” y escanean en segundo plano.

Qué incluye normalmente un “escaneo básico”

El escaneo básico suele ser un motor antivirus (o servicio) más algunas salvaguardas: escaneo AV, comprobaciones de tipo de archivo (magic bytes), límites en archivos comprimidos (zip bombs, zips anidados, tamaño descomprimido enorme) y bloquear formatos que no necesitas.

Si el escáner falla, se queda colgado o devuelve “desconocido”, trata el archivo como sospechoso. Mantenlo en cuarentena y no proporciones un enlace de descarga. Ahí es donde los equipos se queman: “escaneo falló” no debe convertirse en “igual lo publicamos”.

Cuando bloquees un archivo, mantén el mensaje neutral: “No pudimos aceptar este archivo. Prueba con otro archivo o contacta con soporte.” No digas que detectaste malware a menos que estés seguro.

Ejemplo: foto de perfil y subida de documento en una app típica

Considera dos funcionalidades: una foto de perfil (mostrada públicamente) y un recibo PDF (privado, usado para facturación o soporte). Ambas son problemas de subida, pero no deberían compartir las mismas reglas.

Para la foto de perfil, manténlo estricto: permite solo JPEG/PNG, capea el tamaño (por ejemplo 2–5 MB), y re-encodifica en servidor para no servir los bytes originales del usuario. Almacénala en público solo después de las comprobaciones.

Para el recibo PDF, acepta un tamaño mayor (por ejemplo hasta 20 MB), mantenlo privado por defecto y evita renderizarlo inline desde el dominio principal de tu app.

Un modelo de estados simple mantiene informados a los usuarios sin exponer internos:

  • pending: el usuario eligió un archivo, la subida no comenzó
  • uploaded: el almacenamiento recibió los bytes
  • scanning: un job en segundo plano lo está comprobando
  • clean (o rejected): el archivo está disponible (o bloqueado)

Las URLs firmadas encajan bien aquí: usa una URL firmada de corta duración para la subida (solo escritura, una clave de objeto). Emite una URL firmada separada y también corta para la lectura, y solo cuando el estado sea clean.

Registra lo que necesitas para investigar, no el archivo en sí: ID de usuario, ID de archivo, tipo estimado, tamaño, clave de almacenamiento, marcas de tiempo, resultado del escaneo, IDs de petición. Evita registrar contenido bruto o datos sensibles dentro de documentos.

Errores comunes y trampas fáciles

Plan before you code
Use planning mode to map roles, access rules, and retention in one place.

La mayoría de los bugs de subida ocurren porque un pequeño atajo “temporal” se vuelve permanente. Asume que cada archivo es no confiable, que cada URL se compartirá y que cada “lo arreglaremos después” se olvidará.

Las trampas que aparecen repetidamente:

  • Confiar solo en comprobaciones del lado cliente. Los navegadores se evitan en segundos.
  • Permitir que los usuarios influyan en rutas, nombres de archivo o claves de objeto.
  • Hacer archivos públicos “solo por un momento”.
  • Usar URLs firmadas que vivan demasiado o funcionen para varios usuarios.
  • Servir archivos con Content-Type equivocado, permitiendo que el navegador interprete contenido riesgoso.

La monitorización es lo que los equipos se saltan hasta que la factura de almacenamiento se dispara. Sigue volumen de subidas, tamaño medio, principales subidores y tasas de error. Una cuenta comprometida puede subir silenciosamente miles de archivos grandes durante la noche.

Ejemplo: un equipo almacena avatares bajo nombres proporcionados por usuarios como “avatar.png” en una carpeta compartida. Un usuario sobrescribe las imágenes de otros. La solución es aburrida pero efectiva: genera claves de objeto en el servidor, mantiene las subidas privadas por defecto y expone una imagen redimensionada mediante una respuesta controlada.

Lista rápida y siguientes pasos

Usa esto como repaso final antes de lanzar. Trata cada elemento como bloqueador de lanzamiento, porque la mayoría de los incidentes vienen de una salvaguarda faltante.

Lista rápida

  • Valida en el servidor con una lista blanca, comprobaciones reales de contenido (no solo el nombre de archivo) y un tamaño máximo por archivo.
  • Almacena subidas privadas por defecto y comprueba permisos cada vez que un archivo se lea, descargue o previsualice.
  • Si usas subidas con URL firmadas, mantenlas de corta duración, acotadas a una clave de objeto y registra su emisión para rastrear abusos.
  • Cuarentena primero, escanea después: no generes vistas previas ni permitas descargas hasta que el archivo esté limpio.
  • Fuerza un comportamiento de descarga seguro: Content-Type predecible, nombres de archivo seguros y attachment para documentos.

Siguientes pasos que merecen la pena

Escribe tus reglas en lenguaje llano: tipos permitidos, tamaños máximos, quién puede acceder a qué, cuánto viven las URLs firmadas y qué significa “escaneo aprobado”. Eso se convierte en el contrato compartido entre producto, ingeniería y soporte.

Añade algunas pruebas que detecten fallos comunes: archivos sobredimensionados, ejecutables renombrados, lecturas no autorizadas, URLs firmadas expiradas y descargas con “escaneo en proceso”. Estas pruebas son baratas comparadas con un incidente.

Si construyes e iteras rápido, ayuda usar un flujo donde puedas planear cambios y revertirlos con seguridad. Los equipos que usan Koder.ai (koder.ai) suelen apoyarse en el modo de planificación y snapshots/rollback mientras endurecen las reglas de subida con el tiempo, pero el requisito central sigue siendo: la política la hace cumplir el backend, no la interfaz.

Preguntas frecuentes

What’s the minimum I should do to make file uploads “safe enough”?“

Comienza con privado por defecto y trata cada subida como entrada no confiable. Implemente cuatro controles básicos en el servidor:

  • Quién puede subir
  • Qué tipos de archivo aceptas (lista blanca)
  • Tamaño/frecuencia (límites de tamaño + rate limits)
  • Quién puede leerlo después (comprobaciones de permiso por archivo)

Si puedes responder a estas preguntas con claridad, ya estás por delante de la mayoría de los incidentes.

Why are file uploads a common first security incident?

Porque los usuarios pueden subir una “caja misteriosa” que tu app almacena y quizá vuelva a mostrar a otros usuarios. Eso puede provocar:

  • Acceso no autorizado a documentos privados
  • Phishing o toma de cuentas si un archivo se sirve como contenido web confiable
  • Caídas y facturas altas por oleadas de subidas o archivos enormes

Rara vez se trata solo de “alguien subió un virus”.

What’s the difference between storing files and serving files, and why does it matter?

Almacenar es guardar bytes en algún lugar. Servir es cómo esos bytes se entregan a navegadores y apps.

El peligro aparece cuando tu app sirve subidas de usuarios con el mismo nivel de confianza y reglas que tu sitio principal. Si un archivo riesgoso se trata como una página normal, el navegador puede ejecutarlo (o los usuarios confiar demasiado en él).

Un valor predeterminado más seguro es: almacenar de forma privada y luego servir mediante respuestas controladas con cabeceras seguras.

How do I stop users from downloading someone else’s uploaded file?

Usa denegar por defecto y comprueba el acceso cada vez que se descarga o previsualiza un archivo.

Reglas prácticas:

  • Cada registro de archivo debe tener un propietario (usuario/organización) y un propósito (avatar, factura, etc.)
  • Al leer/descargar, verifica que el solicitante esté autorizado para ese archivo específico
  • Evita seguridad basada en carpetas como “todo bajo /uploads/ está bien”
  • Mantén el acceso de soporte temporal y registrado (otorga acceso a un archivo, expira automáticamente)

La mayoría de los errores reales son simples errores de “puedo ver el archivo de otro usuario”.

How do I validate file type without trusting the filename or Content-Type?

No confíes en la extensión del nombre de archivo ni en el Content-Type del navegador. Valida en el servidor:

  • Usa una lista blanca de formatos por característica (por ejemplo, JPEG/PNG para avatares, PDF para recibos)
  • Detecta el tipo en el servidor y verifica las magic bytes (firma del archivo)
  • Renombra los archivos para almacenamiento usando un ID aleatorio; conserva el nombre original solo como metadato
  • Bloquea formatos riesgosos que no necesites (especialmente HTML, SVG y contenido tipo script)

Si los bytes no coinciden con un formato permitido, rechaza la subida.

What limits should I set to prevent upload-based DoS attacks?

Porque las caídas suelen venir de abusos sencillos: demasiadas subidas, archivos gigantes o conexiones lentas que agotan recursos.

Valores por defecto que funcionan bien:

  • Limites máximos por característica (avatares pequeños, documentos más grandes)
  • Aplica límites en varias capas (app + proxy reverso + timeouts)
  • Añade rate limits por usuario y por IP, con límites más estrictos para tráfico anónimo

Trata cada byte como un coste y cada solicitud como un posible abuso.

Should I use signed URLs for uploads, and what’s the safest default?

Sí, pero con cuidado. Las URLs firmadas permiten que el navegador suba/descargue directamente desde el almacenamiento sin hacer el bucket público.

Buenas prácticas:

  • Mantén las URLs de escritura de corta duración (a menudo 1–5 minutos)
  • Usa cada URL solo para una clave de objeto concreta, no para una carpeta
  • Emite URLs solo después de comprobar permisos
  • Registra quién solicitó la URL y para qué archivo

Directo a almacenamiento reduce la carga de la API, pero el alcance y la expiración son innegociables.

What’s a safe step-by-step upload flow I can implement?

El patrón más seguro es:

  1. Crear un registro de subida con estado pending
  2. Subir los bytes a una ubicación privada
  3. Validar tamaño + tipo (magic bytes) en el servidor
  4. Escanear (normalmente asíncrono) y cambiar el estado a clean o quarantined
  5. Permitir descarga/previsualización solo cuando el estado sea clean

Esto evita que archivos “escaneo fallido” o “en proceso” se compartan accidentalmente.

Do I really need malware scanning, and what does “basic scanning” look like?

El escaneo ayuda, pero no es una garantía. Úsalo como red de seguridad, no como único control.

Enfoque práctico:

  • Cuarentena primero: no expongas enlaces hasta que termine el escaneo
  • Escanea de forma asíncrona para escalar; muestra “procesando” al usuario
  • Si el escaneo falla o expira, trata el archivo como sospechoso y mantenlo bloqueado
  • Añade guardias para archivos comprimidos (zip bombs, tamaños descomprimidos enormes) si los permites

La clave es la política: “no escaneado” nunca debería significar “disponible”.

How should I deliver uploaded files safely (headers, domains, downloads)?

Entrega los archivos de forma que evites que los navegadores los interpreten como páginas web.

Buenos valores por defecto:

  • Establece Content-Disposition: attachment para documentos
  • Usa un Content-Type seguro elegido por el servidor (o application/octet-stream)
  • Usa claves de almacenamiento opacas (no nombres de usuario) en las URLs
  • Prefiere un dominio de descarga separado para contenido de usuario cuando sea posible

Esto reduce el riesgo de que un archivo subido se convierta en una página de phishing o ejecute scripts.

Related posts