Sandbox masking tools watch for one trigger: a refresh. Scratch orgs never refresh. They get created from scratch (hence the name), spun up from source-tracked metadata in a DX project, and torn down days later. If your masking policy only fires on sandbox refresh events, every scratch org your dev team creates is invisible to it, and that's exactly where real customer data quietly slips in.
This isn't a theoretical edge case. Developers building or testing against realistic data volumes routinely pull CSV exports from a sandbox, or worse, from production, to seed a scratch org so a feature behaves the way it will in prod. Nobody flags it as a data export event requiring review. It's just a developer trying to get their Apex trigger to pass a test with data that looks real, and in a lot of orgs it is real.
Why Scratch Orgs Sit Outside Normal Masking Coverage
Scratch orgs are provisioned through the Salesforce CLI from a scratch-org-def.json file and metadata in version control. There's no clone-and-mask step in that workflow the way there is with a sandbox refresh. A masking policy configured to intercept and transform PII the moment a sandbox copy completes has no equivalent hook here, because nothing is being copied from a parent org in the first place.
That architecture is a feature for most purposes. Scratch orgs are meant to be short-lived, source-driven, and disposable, which is why Salesforce doesn't build in a data cloning pipeline for them. But that same design means any PII that ends up inside one got there through a side channel: a manual data load, a seed script someone wrote eighteen months ago, or an Apex test factory that was never meant to touch real records.
Admins who treat masking as a sandbox-refresh checkbox miss this entirely. Scratch org creation doesn't show up in the same monitoring dashboards, and most masking vendors don't market scratch org coverage because it falls outside their default trigger model.
How Real PII Actually Gets Into a Scratch Org
There are three common paths, and none of them involve malice.
- CSV seed files committed to the DX repo. A developer exports 500 account and contact records from a sandbox to build a demo, saves them as a CSV in the project folder for "convenience," and that file gets pulled into every scratch org teammates spin up from the same branch.
- Apex test factories built from real record shapes. Someone copies field values from an actual customer record into a test class because it's faster than inventing plausible values, and that pattern gets reused across dozens of test methods.
- Data Loader imports run against scratch orgs directly. A QA engineer needs volume to test a batch job, so they point Data Loader at a sandbox export and load it straight into the scratch org, skipping any masking layer that would normally sit between sandbox and sandbox.
Each of these feels like a shortcut, not a violation. That's what makes the gap persistent: nobody intends to expose a customer's name, email, or phone number in a disposable org, but the convenient path to realistic test data is almost always the unmasked one.
The Compliance Exposure Nobody Accounts For
Under GDPR, a scratch org holding real personal data is processing that data regardless of how long the org lives. A seven-day scratch org with unmasked contact records is still a processing activity, and it still needs a lawful basis, access controls, and a defensible retention story if a regulator or an auditor asks.
The practical risk shows up in a few concrete ways. CI/CD pipelines that auto-create scratch orgs for every pull request can multiply unmasked PII across dozens of ephemeral environments per week. Developer laptops with local DX projects often retain seed CSVs long after the scratch org tied to them has expired. And because scratch orgs are cheap and disposable, teams create far more of them than sandboxes, which means the PII footprint across scratch orgs can outpace the footprint across your tracked sandboxes without anyone noticing.
I'd argue this is the most underpriced risk in a typical Salesforce DX setup. Teams spend real budget masking their partial and full copy sandboxes, then let the exact same unmasked export sit in a Git-tracked seed file that gets loaded into a new environment every time someone runs sf org create scratch.
Building a Masking Policy That Actually Covers Scratch Orgs
Closing this gap means moving the masking control upstream, to the data source, rather than trying to intercept scratch org creation itself.
| Control point | What it does |
|---|---|
| Masked seed data repository | Replace production/sandbox CSV exports in DX projects with pre-masked, version-controlled seed files that still exercise realistic field combinations. |
| Apex test data factories audit | Review existing test classes for hardcoded values that resemble real records and replace them with generated fake data. |
| CI pipeline data load gate | Require any automated data load step in a scratch org pipeline to pull exclusively from an approved masked data source, never from a live sandbox connection. |
| Developer policy and training | Make it explicit, in writing, that exporting sandbox or production records directly into a scratch org is a policy violation, not a convenience. |
The seed data repository is the highest-leverage fix. Once your team has a library of masked, realistic CSV files covering Accounts, Contacts, Opportunities, and Cases, there's no reason for anyone to reach for a live export again. It's faster to use the pre-built file anyway, which removes the incentive that created the gap in the first place.
Where MaskEzee Fits Into the Scratch Org Workflow
MaskEzee's core job is masking sandbox data before every refresh, but the same masking engine that transforms a partial copy sandbox can generate the masked seed files scratch org pipelines need. Instead of exporting raw sandbox data for developer use, teams run that export through MaskEzee once and store the masked output as the canonical seed set for DX projects.
That one change collapses two separate risks into a single control point. The sandbox itself stays protected through standard refresh-triggered masking, and the scratch org seed data inherits the same referential integrity and realistic-but-fake values, so Account and Contact relationships still resolve correctly inside a scratch org built from that data. Developers get data that behaves exactly like production without a single real name, email address, or phone number anywhere in the file.
What to Audit This Week
Start by searching your DX repos for CSV files sitting alongside metadata. Any file with column headers like Email, Phone, or SSN deserves a second look, regardless of how old it is or who committed it.
Next, pull a sample of recently created scratch orgs and check what data loaded into them. If the answer is "whatever the developer had lying around," you've confirmed the gap exists in your org, not just in theory.
Finally, put a masked seed data library on the roadmap before your next DX project kicks off. It's a smaller lift than most teams expect, and it closes a hole that standard sandbox refresh masking was never built to cover.
Frequently Asked Questions
Do Salesforce scratch orgs get masked during sandbox refresh?
No. Scratch orgs are created from metadata and configuration files through the Salesforce CLI, not cloned from a parent org during a refresh event. Masking tools that trigger on sandbox refresh have no equivalent hook for scratch org creation, so any data loaded into a scratch org bypasses that control entirely.
How does real PII end up in a scratch org if there's no data cloning step?
It typically enters through manual data loads, such as a developer exporting sandbox or production records to a CSV and importing them with Data Loader, or through Apex test factories that were written using real record values. These are workarounds developers use to get realistic test data quickly, not a built-in feature of scratch org provisioning.
Is unmasked data in a short-lived scratch org still a GDPR concern?
Yes. GDPR applies to any processing of personal data regardless of how long the environment exists. A scratch org that lives for a week with unmasked contact records still counts as a processing activity and needs a lawful basis and appropriate access controls.
What's the most effective fix for scratch org data exposure?
Build a masked seed data repository that developers pull from instead of exporting live sandbox data. Once a pre-masked, version-controlled CSV library exists for common objects like Accounts and Contacts, there's no practical reason for anyone to reach for a raw export again.
Can a masking tool built for sandboxes also produce scratch org seed data?
Yes, the same masking engine used for sandbox refresh can process a sandbox export once and output a masked file for reuse as scratch org seed data. This keeps referential integrity intact across objects while removing real PII from the data developers load into disposable environments.