If Your Product Takes Photo Uploads, You Are Already Building a Biometric System: Four Questions for Every Image Endpoint
Table of Contents
Disclosure: Ultra Lab, MindThread and Ultra Advisor are products of the same group, Ultra Creation (傲創實業).
TL;DR
- If your product has a path where a user uploads a photo and another face is generated from it, you are already building a biometric system. Whether the feature copy calls it a dress-up, a filter or a game, the data category does not change.
- Every upload endpoint that takes images needs four answers fixed before launch: default, scope, retention, revocation. If you cannot write them down, you should not be collecting faces.
- Engineers see image-to-image. Legal sees identity material. Both are looking at the same API.
- Local inference is not a moral stance. It turns the question of whether data leaves the country into an architecture decision, instead of something you have to judge again every time.
- We have two paths of our own that touch faces, and one of them sends images to a cloud model. The boundaries, and the work we have not finished, are in section six.
Filter copy does not change the data category
The previous two posts looked at the user's side: what happens when a face goes into a cloud generative model (Part 1), and what the terms turn that into (Part 2). This post stands on the other side and speaks to the people building products.
The dividing line is this: the output of a traditional photo-editing tool is "still you"; it adjusts the pixels of the same face. The output of a generative model is "another you": it produces a face that did not exist before, and in the process your face is read in full once.
From an engineering perspective, this is an image-to-image task. From a legal and data protection perspective, it is the collection and processing of identity material. Both sides are talking about the same API, but only one of them will be held accountable.
So the sentence "we are just making a fun dress-up feature" carries no weight in a spec. Classification is based on what your system actually collects, what it keeps and where it sends it, not on the verb on the product page.
Four questions an image upload API has to answer
These four questions are not a list of values; they are fields. Before any endpoint that takes images goes live, the answers have to be written in the documentation. If you cannot write them, the design is not finished.
| Question | Poor answer | Better answer |
|---|---|---|
| Default | Training or "improving the service" is on by default, and users have to find the switch themselves | Off by default; or, more simply, the original image never enters a trainable pipeline at all |
| Scope | The original image is taken as is, with EXIF, the background and anyone else in the frame coming along | Cropped and EXIF stripped before upload; state explicitly that other people's faces are not collected |
| Retention | The image is bound to the conversation, and deleting the conversation does not necessarily delete the file | The original and the generated output each have an expiry time, and the period can be stated |
| Revocation | Only the chat history can be deleted; nobody knows about the rest | Original, generated output and derived permissions are disabled together; for the part that training batches make impossible, say so in plain language |
The point is the phrase in the fourth field: say out loud the part you cannot do. With revocation, most teams can do the first half (deleting files) but not the second half (what has already gone into training cannot be pulled back). Not being able to do it is not the offence; pretending you can is. Writing clearly on the help page which part can be revoked and which cannot is far more honest, and far safer, than a vague line such as "You can delete your data at any time".
Checklist: how we would look at a "selfie dress-up" feature
No stories, just the checks. Run them against your own product:
- Which storage holds the original image? Who has read access? How long is it kept? Does it expire automatically?
- Does it go into a training or "improving the service" pipeline? If there is an opt-out, does it cover what has already been sent?
- Can the output be taken for training again? Many teams guard the input and forget that the output is also a face.
- Besides the face, what else is collected? EXIF, house numbers and documents in the background, company data on a screen, the layout of an ID document.
- If there is a second person in the image, how do you handle it? Is there any mechanism at all, or does it rely entirely on users policing themselves?
- When a user deletes their account, do caches, thumbnails, CDN copies and vector indexes disappear with it?
- Do your terms simply push the rights warranty back onto the user and stop there? If so, that paragraph protects you, not them.
- The third-party vendor layer: whose API do your images pass through? Have you read their retention policy?
The last item is the easiest to miss. Many products keep not a single row of data themselves, yet forward the image untouched to some third-party vision API, and then write "we do not store your photos" in the privacy policy. That sentence is technically true and substantively promises nothing.
Local is not a moral position, it is architecture
We have written about our approach many times: anything that must stay confidential and should not leave the country goes through local Ollama, and the data never leaves this machine.
This is not about being high-minded. It turns a question that would otherwise have to be judged anew every time into a one-off architecture decision. Once "could this leak" has been answered by where things are deployed, you do not have to argue it again on every new feature, and you will not make a different choice on the Friday you are rushing to ship.
In practice, the boundary looks roughly like this:
- Can go to the cloud: public material, images with no faces or documents, illustrations, content that has already been published, de-identified screenshots.
- Should stay local: original frontal face photos, ID documents, customer files, photos of homes and office spaces, any face that is not your own.
The cost has to be stated honestly. Local inference models are usually not as good as frontier cloud models, and the hardware is your own cost. So this is a decision, not a dogma: whether it is worth it depends on how serious the consequences of that data leaking would be. Low consequences go to the cloud; irreversible consequences stay local. Faces belong to the latter, because a face cannot be reset.
Ultra Lab's own red lines
Before writing about others, write about ourselves, including what we have not done yet.
We have two paths that touch faces. First, the one that sends images to a model. MindThread has "image to post": a user uploads a work photo to generate post copy, and the image is converted to base64 and sent to Gemini for image recognition. If the image contains a face, that face is read once by a cloud model at that moment.
Run the four questions above against it and the answers are not pretty: the default is to send it (that is the feature itself); the scope is the full original image, and we have not built a check for whether there is a face in it; retention is in Firebase Storage with no automatic expiry; revocation currently means deleting the post, and the image does not go with it. By the standard of this article, this path is homework we have not finished.
The other path only stores the image for display. UltraSite's business card generator has an optional avatar. The uploaded image is compressed into a small square in the browser and then stored in our database, and it has one purpose only: to be shown on your own card. It does not go into a prompt, does not take part in generation, and is not sent to any generative model. When the public interface looks up the card, it returns whether there is a photo, not the photo itself; fetching the image goes through a separate endpoint, so that crawlers cannot harvest them in bulk.
The same four questions: by default it enters no trainable pipeline; scope is narrowed to one small square image; retention follows the card; revocation works (effective immediately in Firestore, with an invalidation window of up to five minutes for CDN edge caches). This is our answer, not the standard answer, and you are welcome to pick holes in it.
When no email is left to unlock the full report, UltraProbe scans do not store the tested system prompt by default. But the same standard has to be applied back to ourselves: if you tick deep analysis, your prompt is sent to Gemini for one-off inference. We do not write it to storage ourselves, but it does pass through a third party. To avoid third parties entirely, run only the deterministic scan without deep analysis ticked. This is exactly the "we do not store your photos" trap described earlier, and we are standing at its edge too.
Then comes the thing this post most needs to make clear.
ADP (AI Data Protection) in AASS asks "have you given AI data you should not have given it". What actually runs in the published ultraprobe package is ten categories and twenty-one patterns, all pure regex: Taiwan national ID numbers, names, email addresses, mobile numbers, addresses, dates of birth, credit cards, bank accounts, API keys, internal IPs.
Here I have to correct something of our own. In past articles we also listed Taiwan's Unified Business Number (the company tax ID), JWTs, passwords, private keys and database connection strings as part of this list. Those rules were indeed written, but they were written in a file that nothing references, which is the same as never being wired in. Written is not the same as running; I only found this by checking myself.
It cannot detect faces. The online scanner currently covers two dimensions, AVS and PDS, and face input is not among them. Turning "is there a face in this input" into a checkable item is ADP's next question, not an existing feature.
I am spelling this out here because the whole argument of this series is "do not claim what you cannot do". If I said that while letting you believe we can already scan for faces, these three posts would have been written for nothing.
Also: this post is a spec, not "scan it and you are safe". No tool can answer those four questions or that checklist for you. What a tool can check is whether you have written the answers into your system; it cannot decide for you what the answers should be.
The last rule applies to us as well: if a future feature genuinely needs faces or ID documents, it must be treated as a new product category, with separate consent obtained, defaulting to local processing or zero retention, and never added as a small extra option inside an existing tool.
Wrapping up
Whether a product is building a biometric system is not decided by what it calls itself. It is decided by what its upload endpoint collects.
Default, scope, retention, revocation. Four questions, four fields. They are not hard to answer; what is hard is being willing to answer them before launch, under the pressure of a feature schedule.
If you can write these four things down, the decision to collect faces has at least been made, rather than defaulted into. If you cannot, do not collect them yet.
If you want to know what your application looks like to AI, UltraProbe can scan it and show you, but remember its scope: it checks whether you have written the answers into your system, not come up with the answers for you.
Further reading
- Part 1 of this series: You think you are asking ChatGPT what you would look like; the system is collecting a biometric credential
- Part 2 of this series: ChatGPT's terms treat your face as "content"
- We defined the security standard for the AI era: AASS v1.0
- How do we prove we actually do AI?
FAQ
How do I tell whether my product counts as a biometric system?
Look at what the upload endpoint actually receives, not at the verb on the product page. As soon as there is a path for users to upload photos of faces, the data category is identity material. From an engineering perspective it is an image-to-image task; from a data protection perspective it is the collection and processing of identity material. Both sides are talking about the same API.
Which four questions should be answered before launch?
Default (whether training or service improvement is on by default), scope (whether you take the full original image or crop it and strip EXIF), retention (how long before the original and the generated output each expire), and revocation (whether everything can be disabled together, and which part cannot be undone). The four answers have to be written in the documentation; if you cannot write them, the design is not finished.
How should I handle the part of revocation I cannot deliver?
State it as it is. Most teams can delete files but cannot pull back what has already gone into a training batch. Writing clearly on the help page which part can be revoked and which cannot is far more honest, and far safer, than a vague line such as "You can delete your data at any time". Not being able to do it is not the offence; pretending you can is.
Which image work should stay on the local machine?
Original frontal face photos, ID documents, customer files, photos of homes and office spaces, and any face that is not your own. Public material, images with no faces or documents, and de-identified screenshots can go to the cloud. The cost of local inference is model quality and hardware, so this is a decision rather than a dogma: what has irreversible consequences stays local, and faces belong in that group.
Can UltraProbe's ADP detect faces uploaded by users?
No. What actually runs in the published package today is PII detection across ten categories with twenty-one pure-regex patterns (Taiwan national ID number, name, email, mobile number, address, date of birth, credit card, bank account, API key, internal IP), and the online scanner covers two dimensions, AVS and PDS. Turning "is there a face in this input" into a checkable item is the next question, not an existing feature.