Treat availability as an explicit release decision
Model uploaded, validating, scanning, processing, available, rejected, and failed states. A file stored successfully is still untrusted. Every read and download path should check the release state before serving content.
Store owner, tenant, object key, immutable object version, size, checksum, expected type, scan policy, and result timestamps. Keep rejection distinct from infrastructure failure so users do not see an unsafe file mislabeled as temporarily delayed.
Upload into private storage with bounded authority
Resolve user and tenant on the server before issuing a narrowly scoped upload authorization. Limit destination, accepted size, expiry, and method as supported by the storage platform. Use random internal object keys and keep original filenames as validated display metadata.
After upload, independently verify stored size and object identity before scheduling processing. Do not trust a browser completion callback as proof of those properties. Expire abandoned multipart uploads and staging objects under a documented cleanup policy.
Bind validation and scanning to the exact bytes
Use immutable versions or copy completed uploads to a write-protected processing location. A scan verdict for yesterday's bytes must not authorize an object that can be overwritten at the same key today.
Include object version and checksum in every job and result. Replacing an attachment should create a new version that passes the pipeline independently. Prevent client credentials from writing to already approved artifacts or modifying their release metadata.
Constrain parsers, archives, and processors
Validate signatures and content structure according to allowed formats, while treating extensions and declared MIME types as hints. Limit dimensions, page counts, decompressed bytes, nesting, processing time, memory, and output size where applicable.
Run parsers and converters with minimal privileges and restricted network and filesystem access. Avoid arbitrary URL fetches and executable macros. Archive support needs its own policy for paths, symlinks, nested content, and expansion rather than an automatic extract-and-trust step.
Keep uncertain results quarantined
Record scanner identity, engine or policy version, verdict, and safe failure reason. A timeout or unavailable scanner should leave the file unavailable when scanning is required. Retry bounded transient failures without changing the verdict to clean merely to clear the queue.
Define review and deletion rules for rejected files. If administrators can override a verdict, require narrowly scoped authority, a recorded reason, and a clear policy. Do not let a general-purpose retry endpoint silently bypass the required checks.
Publish a verified artifact through an authorized boundary
Process thumbnails or previews from approved inputs in isolated workers and validate their outputs too. Mark the released version available only when all required steps complete and the final object is stored durably.
Recheck current user and tenant permission before issuing a short-lived download URL or streaming the file. Use safe content types and filenames, and choose inline display only for formats the application intentionally supports. Keep unsafe originals separate from sanitized previews.
Test replacement, replay, and scanner outages
Try oversized and malformed files, mismatched content types, compressed expansion, overwritten keys, duplicate storage events, worker crashes, delayed scan results, and permission revocation before download. Verify that a verdict can authorize only its bound object version.
Monitor quarantine age, scan latency, rejection categories, processor resource use, stale uploads, and released-file counts. Reconcile pipeline state with object storage, and apply retention to both originals and derived artifacts.
Apply the security guidance to your provider and infrastructure
OWASP recommends layered upload controls, including type and size restrictions, protected storage, and antivirus or sandbox checks where available. A scanner is one layer; a clean result cannot prove an arbitrary file is harmless.
Build a more dependable Next.js application
Endurance Softwares helps teams design, build, test, and operate production-ready Next.js platforms.
