A gift card image is not an ordinary profile photo. It can contain a redeemable code, a PIN, a receipt, an email address, an order number, and location metadata from the camera. A single authorization bug can therefore expose both personal data and something that behaves like a bearer secret.

This article designs the upload path as a security boundary. The examples are implementation-neutral TypeScript so the controls can be mapped to your framework, image decoder, object store, and queue.

The goal is not “secure file upload” in the abstract. It is a narrower property:

Collect only the evidence needed for a decision, keep the original out of normal review paths, and make every retained copy private, attributable, and short-lived.

Start with staged disclosure