"We mask Aadhaar numbers" is a claim. An auditor asks how you know, and the usual answer is that the vendor said so. That is not evidence, and the gap between the two is where most masking programmes turn out to be weaker than the slide deck.
This is a practical piece about what to keep, because the controls that make masking auditable are cheap if you design them in and close to impossible to reconstruct afterwards. If you already run masking in production and cannot answer the five questions below from data rather than from memory, that is the gap.
On this page
Five questions an auditor will ask
In rough order of how uncomfortable they get.
- Which documents were masked? Not "all of them" — a list, joinable to your document inventory.
- How do you know masking succeeded on each one? Per document, not in aggregate.
- What happened to the ones where it did not? There will be some. A programme claiming a hundred per cent success rate has stopped measuring, not achieved perfection.
- Can the original be recovered from the masked output? For PDFs this is a real question with a testable answer.
- Where are the unmasked originals now? The one that tends to end the conversation.
None of these are answerable by pointing at a masking service. They are answerable by records your own pipeline kept at the time.
The number that makes it auditable
The single most useful thing a masking step can return is a count of how many regions it redacted. Not a success boolean — a count.
A boolean conflates two very different outcomes: "I found an Aadhaar number and covered it" and "I looked, found nothing, and am returning your document unchanged". Both are HTTP 200. Both are "success" from the service's point of view, because nothing went wrong. Only one of them produced a masked document.
A count separates them, and it turns masking from an assertion into a measurement. Our API returns it as a response header:
X-Masked-Count: 2 # two regions redacted, both sides of the card X-Masked-Count: 0 # nothing found, document returned as supplied
Store that count against the document identifier, and the first two audit questions above become a database query rather than an investigation. Store nothing, and you are relying on the absence of error logs as proof that a thing happened, which is not the same claim at all.
The silent failure that looks like success
A count of zero is the failure mode worth designing around, because it is the one that produces a clean-looking pipeline and an unmasked archive.
It happens for mundane reasons. Glare on a laminated card. A fold running through the digits. A photograph taken at an angle in poor light by a field agent standing in a customer's doorway. A scan where the number sits in the margin that got cropped. OCR is probabilistic, and on real documents rather than clean test files a few per cent will not yield a readable number.
The question is what your pipeline does next, and there are only three honest options.
Pass the original through. Simplest to implement, and it silently recreates the exact problem you deployed masking to solve — with the added harm that the document is now filed as masked. If you do this, your masked archive contains unmasked documents and nothing in your records distinguishes them.
Reject the upload. Defensible, and it fails a customer mid-onboarding because of lighting. Whether that is acceptable depends on how much of your volume it affects, which you should measure before choosing.
Quarantine for manual handling. Where most teams land. It works as long as the quarantine is a named, access-controlled, time-limited location with someone accountable for draining it — and not, as it frequently becomes, the same bucket as everything else with a prefix nobody monitors.
Whichever you choose, the auditable artefact is the same: a record that this document had a count of zero and was routed accordingly.
Testing that redaction is real
This is the test most worth running against any masking tool, including ours, and it takes about thirty seconds.
A PDF has a text layer separate from what is drawn on the page. A tool that "masks" by drawing a black rectangle over the number has changed what a human sees and left the digits fully intact underneath, recoverable by anything that reads the text layer — which includes copy-paste, search indexing, and any downstream system that extracts text.
# Mask a PDF containing a known Aadhaar number, then:
pdftotext masked.pdf - | grep -o '[0-9]\{4\}'
# If the first eight digits of the original number appear
# in that output, the redaction is cosmetic. Real redaction
# removes the pixels and the text, so nothing comes back.
Run the same test on image output by checking that the masked region is a solid fill rather than a semi-transparent overlay. Both failures are invisible on screen and obvious to a script, which is exactly the sort of finding an auditor with a laptop enjoys producing.
Sampling the archive, not the happy path
A masking programme is usually validated against a handful of clean documents chosen by whoever set it up. That tells you the integration works. It tells you nothing about your document population.
Sample from the actual archive instead, and stratify deliberately: the oldest documents, the smallest file sizes, the ones from your least-equipped collection channel, multi-page PDFs, and anything scanned before your current capture app existed. Those strata are where failures concentrate, and a random sample across the whole corpus will under-represent them because most of your volume is recent and clean.
A hundred documents drawn that way, checked by hand, will tell you more about your real masking rate than fifty thousand processed without inspection. And the exercise produces a written record of a control test, which is itself the artefact an auditor is looking for.
Where the originals are, and why that ends the conversation
The fifth question on the list above is the one that tends to close an audit meeting, so it is worth answering before someone else asks it.
Masking produces a new document. It does not, by itself, do anything about the one it was derived from. Whether the original survives is a property of your pipeline, not of the masking tool, and it is decided by a handful of implementation details that are easy to get wrong without noticing.
The upload buffer. If the unmasked file is written to disk or object storage before being passed to masking, that write is your exposure, and its lifetime is however long your cleanup job takes — which in practice is however long since anyone checked that the cleanup job still runs. Masking in the request path, before the first persist, is the only design where this question has a clean answer.
Queue payloads and retries. Asynchronous designs frequently put the document itself on a queue. Those messages persist, sometimes for days on a dead-letter queue after a failure, and they are rarely covered by the retention policy that governs the document store. A dead-letter queue holding unmasked KYC documents from six months of intermittent failures is a common and genuinely unpleasant finding.
Backups and snapshots. If unmasked originals were ever persisted, they are in your backups, and they will outlive the masking programme by the length of your backup retention. This one cannot be fixed retroactively in any satisfying way, which is the strongest practical argument for masking at intake rather than after: it is the only approach where there is nothing in the backups to worry about.
Logs and error reporting. An exception handler that attaches the request body for debugging will cheerfully write an Aadhaar document into your logging platform, where it is searchable by a much wider group of people than can open the document store, and where retention is usually set by the logging vendor's default rather than by your policy.
The honest position, if any of these apply to you, is to say so and scope the remediation, rather than to answer the question as though masking implied deletion. Auditors are considerably more comfortable with a known gap and a dated plan than with an assurance that does not survive the follow-up question.
What a defensible masking log contains
Per document, at the time of processing, and joinable to your document inventory:
| Field | Why it is there |
|---|---|
| Document identifier | Joins the log to the file and to the customer record |
| Timestamp | Establishes masking happened before the document was persisted, not after |
| Regions redacted | The measurement; zero is a finding, not a pass |
| Outcome routing | Stored, rejected or quarantined — and if quarantined, when it was drained |
| Tool and version | Lets you scope an incident if a detection bug is found later |
| Source channel | Makes failure clustering visible by capture app, branch or agent |
Note what is deliberately absent: the Aadhaar number, in any form, hashed or otherwise. A masking log that records the value it redacted is a database of Aadhaar numbers with extra steps, and it tends to be less well protected than the document store because nobody thinks of it as sensitive.
Note also what the timestamp is doing. It is the field that distinguishes "we mask at intake" from "we ran a masking job over the archive last quarter", and it is the difference an auditor cares about most, because only one of those means unmasked copies never existed downstream.
Questions worth asking a vendor
Including us. If a supplier cannot answer these crisply, that is information.
- Does the response distinguish "masked" from "nothing found", and how?
- Is redaction destructive to the underlying text layer in PDF output, and can you demonstrate
it with
pdftotext? - Are twelve-digit runs validated against the Aadhaar checksum, or matched by length? Length matching means Virtual IDs and enrolment numbers get treated as Aadhaar numbers.
- Are both sides and all orientations scanned, or does detection stop at the first number found?
- Is the document retained, and if so for how long and where? "Processed in memory" and "deleted after 24 hours" are materially different answers.
- What is billed when detection finds nothing? If a zero-count response is chargeable, the vendor has an incentive you should know about.
The five tests we think are worth running against any masking tool, set out in more detail, are in how to choose Aadhaar masking software.
This describes control design and evidence, not legal or audit advice. What your regulator or internal audit function will accept depends on your licence and their methodology, and is worth confirming with them rather than with a vendor.
Masking you can evidence. Every response carries X-Masked-Count, so your pipeline can record per document how many regions were redacted — and branch on zero rather than filing an unmasked document as masked. Nothing is retained.