HOW YOUR FILES ARE HANDLED

Security

People upload personal photos here. The architecture is designed so that the safest possible thing — deletion — happens by default, fast, and that nothing uploaded is ever publicly reachable.

Upload handling

  • Chunked transfer — images arrive in 512 KB chunks, which keeps each request small and avoids depending on large PHP upload limits on shared hosting.
  • Randomized storage — each upload gets a random 36-character token; chunks are stored under that token with owner-only permissions (0700 directory, 0600 files).
  • No original filenames — your filename is used only for display and filename forensics; nothing is stored under a user-controlled name, which removes path-traversal and overwrite risks.
  • Type validation by content — after assembly, the file is validated by magic numbers, MIME detection and pixel decoding. Files that are not genuinely JPG/PNG/WebP are rejected and deleted. Extensions are never trusted.
  • Size limits — 20 MB maximum, enforced client- and server-side.

Temporary processing & deletion

  • Deletion after analysis — the assembled original is deleted via unlink() immediately after the report is generated (a small thumbnail remains for the report page).
  • Automatic expiry — a cleanup routine runs on every request and removes anything older than 15 minutes, including abandoned partial uploads.
  • Report expiry — reports (and their JSON exports) stop resolving when their token directory is removed; thumbnails refuse to serve past expiry.
  • No copies elsewhere — the application does not copy uploads to any database, cloud storage or third-party processor; analysis is plain PHP on the web server itself. (Application-level retention is zero; any infrastructure-level backups are governed by the hosting provider's policies, which we do not control.)

Access controls

  • Storage is not web-accessible — direct requests to /uploads/… return 404 at the web-server level; files are served only through internal endpoints that validate the token format.
  • Unpredictable report URLs — report links require the random token; there is no listing, enumeration or search of reports.
  • Noindex everywhere it matters — report and thumbnail responses send X-Robots-Tag: noindex headers and the pages carry noindex meta tags, so temporary URLs can't become search content even if someone pastes one publicly.
  • Rate limiting — repeated analysis of the identical file is throttled within a short window, using only a truncated hash prefix for comparison (no identifying data stored).

Application hardening

  • XSS protection — metadata is attacker-controlled data. Every metadata value, filename and string rendered on a report page is HTML-escaped at output; JSON export sets nosniff and downloads as an attachment.
  • No code execution in storage — the upload directory blocks PHP execution and directory listings via server configuration.
  • Token and path safety — all token/path inputs are filtered to a strict allowlist ([A-Za-z0-9_-]) before touching the filesystem.
  • Security headersX-Content-Type-Options: nosniff, Referrer-Policy, X-Frame-Options and a restrictive Permissions-Policy are set site-wide via .htaccess.
  • Minimal surface — config and environment-style files are denied by the server configuration; the production deployment contains no test or debug endpoints.

Honest boundaries

  • Report links rely on link secrecy, like most web links. Don't paste a report URL anywhere you wouldn't want the report seen until it expires.
  • Analysis happens on a shared-hosting web server in memory/disk during processing; we operate it with least privilege, but "temporary server processing" is inherent to any server-side analyzer.
  • If you need analysis that never leaves your device at all, use the browser-side preflight (dimensions, SHA-256, entropy preview) and compare mode — they run entirely client-side.

Reporting a vulnerability

Found something? Please email hello@picturematters.in with details and reproduction steps. We take security reports seriously and will respond as quickly as we can — please allow a reasonable window for fixes before public disclosure.