On this page
- Quick read
- Readiness check
- Inventory the fields before choosing a method
- Write the ticket with fixture provenance
- Choose methods that fit the field and the test
- Review the masked output, not only the script
- Control the export, the masked set, and the clock
- Attack the masked set with combinations
- Measure coverage and residual risk
- Close with a provenance record and a sharing rule
- Role brief
- Frequently asked questions
- Sources
Is the handoff ready?
Use these checks before access expands or the first ticket begins.
Fields
Ready: Named direct and indirect identifiers with owners
Needs work: A general instruction to anonymise
Method
Ready: Chosen per field with reversibility stated
Needs work: One hash applied to everything
Output
Ready: Masked set reviewed for joins and free text
Needs work: A row count and a spot check
Sharing
Ready: Owner approves recipients and retention
Needs work: A link in a chat thread
Inventory the fields before choosing a method
Masking fails when the inventory is short. List direct identifiers such as name, email, phone, and account number, then indirect identifiers such as postcode, birth date, job title, and rare diagnosis. The combination is often enough to re-identify a person even when each field looks harmless.
Include free text, file names, and nested JSON. A support note or an uploaded document can carry the same identifiers that were removed from the structured columns.
Give each field an owner and a purpose. A Philippines-based programmer can then mask to the purpose rather than to a vague standard, and the reviewer can see why a field is present at all.
Count the fields you remove as well as the fields you mask. A fixture that does not need a phone number is safer without the column, and removal is easier to explain than a clever transformation.
Write the ticket with fixture provenance
The ticket names the source system, the export query, the row limit, the fields, the masking method per field, the storage location, and the recipients. It also names the reviewer and the retention date.
Provenance is part of the deliverable. Record the export revision, the extraction time, the row count, and the transformation script revision. A fixture set with no provenance cannot be refreshed or defended later.
Keep the first ticket to one domain, such as billing records or support tickets. A whole database export is a project with legal review, not a maintenance task.
Choose methods that fit the field and the test
Replacement with realistic fake values keeps a demo readable. Hashing keeps joins stable but is not anonymous when the input space is small, because a phone number or an email can be guessed and hashed again.
Tokenisation with a controlled mapping preserves joins and allows reversal by an authorised holder. The mapping is then a sensitive asset with its own access rule, not a helper file in the repository.
Aggregation or suppression removes the field entirely. That is often the right choice for a field the test does not need, and it is the easiest method to defend in review.
- Direct identifiers: replace with fake values or remove.
- Join keys: tokenise with a controlled mapping.
- Quasi identifiers: generalise or bucket.
- Free text: redact, replace, or drop the column.
Review the masked output, not only the script
A correct script can still produce a leaky set. Check that masked emails remain unique where the test needs uniqueness, that joins still match, and that no original value appears in a comment, a file name, or a log line.
Search the output for the original values you know, including partial strings. A reviewer with a small sample of source records can run that search quickly and catch a column the script missed.
Test the rare record. A single row with a distinctive combination can be identified even in a large masked set, and that is the row a reviewer should look at first.
Control the export, the masked set, and the clock
The programmer needs a read only export path and a sandbox storage location. They do not need the production database, the customer support console, or the ability to widen the export query.
Set a retention date before the work starts. A masked set that lives forever in a shared drive becomes an unmanaged copy of customer data, and the masking effort is wasted.
Decide who can download the set, where it may be stored, and what happens at the retention date. That decision belongs to the company owner, not to the programmer who built the fixture.
Attack the masked set with combinations
Try to re-identify one record using three or four fields together. If a birth date, a postcode, and a job title still point to one person, the set needs more generalisation.
Check partial masking. An email that keeps the local part, or a phone that keeps the last four digits, can be enough when combined with a public profile.
Check the side channels as well: commit history, test output, screenshots, and error messages. A masked database with an unmasked screenshot in the pull request is not masked.
- Re-identification attempt with three quasi identifiers.
- Partial mask that keeps a recognisable fragment.
- Original value found in a log, file name, or screenshot.
- Join across two masked sets that were tokenised with different mappings.
Measure coverage and residual risk
Measure fields masked divided by fields identified, records with a re-identification attempt reviewed divided by records sampled, and sets past their retention date divided by all sets. Report the sample size.
Track the count of masking exceptions approved by the owner. Exceptions accumulate quietly and turn a strict rule into a habit.
Report the age of each stored set. A set created before the current field inventory may be missing a column that was added later, and its age is the fastest way to spot that gap.
Review before each new fixture share and quarterly for stored sets. Any schema change that adds a personal field triggers a new inventory.
Close with a provenance record and a sharing rule
The handoff contains the field inventory, the methods, the script revision, the output checks, the retention date, the recipient list, and the exceptions. It also names the owner who can approve a new share.
Accept the work when a reviewer can regenerate the masked set from the recorded export revision and verify the same output checks without the original programmer.
Record who holds the token mapping and when it was last reviewed. A mapping with no owner is a master key with no lock.
Copy-ready brief
Put the operating agreement in writing.
One data domain with a named export query and row limit.
Per field choice with reversibility and mapping owner.
Uniqueness, joins, free text, screenshots, retention.
Company owner approves recipients, storage, and deletion.
Frequently asked questions
Is hashing a personal identifier enough?
Not on its own. A small input space can be guessed and hashed again, so treat hashed identifiers as sensitive unless the mapping is removed and the space is large.
Can masked data live in the test repository?
Only with owner approval, a retention date, and access control. A repository is a shared copy, not a private sandbox.
Who approves sharing a fixture set with a vendor?
The company owner responsible for the data, after reviewing the field list and the recipient controls.
Sources
- NIST Privacy Framework
Framework for identifying and managing privacy risk in data handling.
- OWASP Application Security Verification Standard
Data protection verification topics relevant to test environments.
- NIST Secure Software Development Framework
Environment separation and artifact protection practices.
- CISA Secure by Design
Secure defaults and minimisation principles for shared data.
